Python operators: esquema y explicación

Los operadores Python te ayudan a trabajar con valores (operandos), a modificarlos o a vincularlos entre sí. Los operadores pueden ser por ejemplo lógicos o aritméticos.

¿Qué son los operadores de Python y cómo funcionan?

Un operador es un carácter para una operación. Suelen utilizarse sobre todo para vincular múltiples operandos, y normalmente como resultado se crea un valor nuevo. Aplicar un operador a un único operando lo modifica.

Probablemente, el ejemplo más claro de operador Python es unir dos cifras con el operador de la suma, es decir, poniendo un más entre las cifras. Python evalúa la expresión y devuelve el valor correspondiente:

1 + 1

Una característica de Python es que, además de símbolos, también utiliza palabras cortas como operadores, por ejemplo, “and”, “or”, “is”, “not” e “in”. La combinación de operadores y operandos da como resultado una expresión:

1 + 1 == 2

¿Qué tipos de operadores Python hay?

Python cuenta con distintas clases de operadores que funcionan con distintos tipos de operandos y devuelven resultados de un tipo determinado. He aquí un esquema de los distintos tipos de operadores de Python:

Clases de operadores de Python

Explicación

Operandos

Resultado

Resumen de operadores

Operadores aritméticos

Unen dos cifras y crean una nueva

Cifras

Cifra

+, -, *, /, //, %, **, @

Operadores de comparación

Comparan dos expresiones entre sí

Expresiones

Booleano

<, >, ==, !=, <=, >=

Operadores lógicos

Vinculan expresiones en contexto booleano

Expresiones

Última expresión evaluada/booleano

and, or, not

Operadores bit a bit

Manipulan números enteros como secuencias binarias

Cifras

Cifra

<<, >>, &, |, ^, ~

Operadores de asignación

Asignan un nombre a un valor

Lvalue, Rvalue

– / expresión evaluada

=, :=, +=, -=, *=, etc.

Operadores de identidad

Determinan si dos nombres se refieren al mismo objeto

Objetos

Booleano

is, is not

Operadores condicionales

Devuelve uno de dos valores en función de una condición

Expresión, condición, alternativa

Expresión/alternativa

... if ... else ...

Operadores de conjuntos

Unen dos conjuntos/enlazan conjuntos

Conjuntos

Conjunto/booleano

&, |, ^, -, <, >, <=, >=

Operadores de membresía

Prueban si un iterable contiene un objeto determinado

Objeto, iterable

booleano

in, not in

Operador de concatenación

Concatena secuencias

Strings / listas / registro

String / lista / registro

+

Operadores índex y slicing

Entre uno o más elementos iterables

Iterable, índex / Slice

String / Lista / registro

[], [::]

Además del tipo de operando y el valor que devuelve, los operadores se clasifican según su “aridad”. La aridad de un operador no tiene nada que ver con su color. Este concepto indica el número de operandos que une un operador. En la mayoría de los casos, se utilizan operadores “binarios” que conectan dos operandos, pero también hay operadores “unarios” que solo tienen un operando, u operadores “ternarios”, que vinculan tres operandos:

Aridad del operador Cantidad de operadores Ejemplo
Unario Un operando not single_value
Binario Dos operandos left_operand + right_operand
Ternario Tres operandos some_value if condition else other_value

Considerar la precendencia de los operadores

Para utilizar los operadores Python hay que entender su precedencia. El concepto sigue el “orden de los operadores” de la aritmética. A modo de recordatorio: la expresión 3 * 8 + 2 se interpreta como (3 * 8) + 2 y no como 3 * (8 + 2). Al igual que en sumas y en multiplicaciones, el resto de Python operators también se rigen por normas de precedencia. He aquí un ejemplo de una expresión con los operadores lógicos “and”, “or” y “not”:

if is_user and is_user_logged_in or is_admin and not login_blocked:
    ...

Si no sabes cuáles son las normas de precendencia de los operadores Python implicados, no puedes decidir cómo se relacionan los términos entre sí. Y si además hay varios operadores en una expresión, la cosa se complica rápidamente. En general, es mejor no confiar en que se vayan a entender las reglas implícitas e introducir paréntesis explícitamente para aclarar las relaciones entre los términos de una expresión:

if (is_user and is_user_logged_in) or (is_admin and not login_blocked):
    ...

Como comparativa, te mostramos los mismos términos agrupados de forma distinta con otro enunciado de ambas expresiones:

if (is_user and is_user_logged_in or is_admin) and not login_blocked:
    ...

Operadores sobrecargados, métodos dunder y funciones del Python Operator

Hay operadores Python que pueden usarse en más de una operación. Un buen ejemplo de ello es el símbolo más, que sirve de operador para sumar cifras y también para concatenar secuencias como strings o listas. Aquí sumamos dos cifras con el operador de sumas:

8 + 3 == 11

Con el mismo operador, concatenamos dos strings:

"Walter" + "White" == "WalterWhite"

También permite concatenar listas:

['Jack', 'Jim'] + ['John'] == ['Jack', 'Jim', 'John']

Los distintos usos del signo más como operador reflejan un concepto común en informática. Un “operador sobrecargado” realiza diferentes operaciones en función del tipo de datos de los operandos.

¿Cómo funcionan los operadores sobrecargados en Python? En general, un operador que incluye operandos se interpreta como una llamada a la función correspondiente. Más concretamente, la llamada se hace al método dunder del primer operando, que recibe el otro u otros operandos como argumentos. “Dunder” viene de “double underscore”, es decir, “doble guion bajo”. El operador “más” corresponde al método dunder de esta manera __add__(). Los objetos que implementen métodos __add__(), pueden vincularse con el operador “más”. Lo que constituya el vínculo dependerá del propio objeto.

Además del método dunder, el módulo operator contiene funciones que encapsulan las funciones de los operadores Python. De esta manera, el “operator.add(a, b)“ llama al método dunder a.__add__(b), que corresponde a la expresión a + b. En este artículo te iremos explicando la función existente para cada operador. La función del operador lleva el mismo nombre que su método dunder, así que puedes utilizarlos como referencia para implementar tus propias funciones de operadores:

Operador Función Método dunder
a + b operator.add(a, b) a.__add__(b)

Los operadores usan la llamada notación de infijo, que introduce los operadores entre los operandos. En cambio, en el estilo funcional, se utiliza la notación de prefijo. Ambas grafías son adecuadas:

Notación Uso Ejemplo
Infijo Operadores a + b
Prefijo Funciones + a b / add(a, b)

Veamos un ejemplo. Definimos dos cifras y las sumamos con el operador, la función y el método dunder correspondiente:

import operator
a = 42
b = 69
assert a + b == operator.add(a, b) == a.__add__(b)

Con las funciones del Operator también pueden escribirse expresiones más complejas. He aquí una combinación de operador de suma y de igual en notación de prefijo:

import operator
assert 'Py' + 'thon' == 'Python'
assert operator.eq(operator.add('Py', 'thon'), 'Python')

Esquema de los operadores de Python

Adentrémonos en las once clases de operadores Python.

Operadores aritméticos

Los operadores aritméticos de Python hacen operaciones de números y obtienen como resultado otro número. A excepción del más o del menos unario, se trata de operadores binarios. He aquí un esquema:

Operador Significado Función Ejemplo
+ Suma / más unario add(a, b) / pos(a) 5 + 3 == 8 / +8 == 4 + 4
- Resta / menos unario sub(a, b) / neg(a) 7 - 2 == 5 / -4 == 2 - 6
* Multiplicación mul(a, b) 2 * 3 == 6
/ División real truediv(a, b) 8 / 2 == 4.0, 7 / 2 == 3.5
// División de números enteros hasta el siguiente entero más pequeño floordiv(a, b) 8 // 2 == 4, 7 // 2 == 3
% Módulo: cantidad restante de la división de enteros mod(a, b) 8 % 2 == 0, 7 % 2 == 1
** Potenciación pow(a, b) 2 ** 3 == 8, 10 ** -1 == 0.1
@ Multiplicación de matrices matmul(a, b)

La operación de módulos suele utilizarse para averiguar si un número es par. Si se divide un número par por dos, el resto es cero. Definimos una función con el operador de módulos:

def is_even(number):
    return number % 2 == 0
# test
assert is_even(8) and not is_even(7)

La multiplicación de matrices requiere usar un paquete como NumPy.

Operadores de comparación

Los operadores de comparación de Python declaran el orden que hay entre dos elementos. Proporcionan un resultado booleano y se utilizan especialmente para los algoritmos de ordenación:

Operador Significado Función Ejemplo
< Menor que lt(a, b) 3 < 1, 'a' < 'z'
> Mayor que gt(a, b) 4 > 2, 'z' > 'a'
== Igual eq(a, b) 'a' == 'a'
!= Desigual ne(a, b) 1 != 2, 'Jim' != 'Jack'
<= Menor igual le(a, b) 9 <= 10, 10 <= 10
>= Mayor igual ge(a, b) 11 >= 10, 10 >= 10

Operadores lógicos

Los operadores lógicos de Python “and” y “or” conectan varios operandos siguiendo la lógica booleana. Ambos operadores dan como resultado el último objeto evaluado. El operador lógico de Python “not” interpreta un objeto en el contexto booleano y niega su valor verdadero:

Operador Significado Función Ejemplo
and Y lógico Sin correspondencia directa True and False == False, 'name' and ... == ...
or O lógico Sin correspondencia directa False or True == True, a = '' or 'Default'; assert a == 'Default'
not Negación not_(a) not True == False

Es útil visualizar el efecto de las operaciones lógicas en una tabla de la verdad. Este es el Y lógico:

and

True

False

True

True

False

False

False

False

Este es el O lógico:

or

True

False

True

True

True

False

True

False

Los operandos de los operadores booleanos de Python no se limitan a variables booleanas. De hecho, todos los objetos de Python pueden interpretarse en contexto booleano. Los siguientes objetos se evalúan como False en contexto booleano, por lo que se describen como “falsy”:

Objeto Explicación
False, None Constantes falsas por definición
0, 0.0, Decimal(0), Fraction(0, 1), etc. Cifras que representan cero
'', (), [], {}, set(), range(0), etc. Colecciones o secuencias vacías

Operadores bit a bit

Los operadores bit a bit de Python operan con números enteros interpretados como secuencias de bit. A excepción del operador bit a bit not, son principalmente binarios:

Operadores

Significado

Función

Ejemplo

<<

Desplaza la secuencia de bits a la izquierda

lshift(a, b)

5 << 3 == 5 * 2 ** 3

>>

Desplaza la secuencia de bits a la derecha

rshift(a, b)

1 >> 1 == 0, 8 >> 1 == 4

&

Vincula dos secuencias de bits con and

and_(a, b)

``

|

Conecta dos secuencias de bits con or

or_(a, b)

``

^

Vincula dos secuencias de bits con xor

xor(a, b)

``

~

Invierte la secuencia de bits con not

invert(a)

``

Los operadores bit a bit son aptos para operaciones matemáticas optimizadas. Por ejemplo, el desplazamiento a la izquierda corresponde a una multiplicación con potencia de dos:

Expresión

23 = 8

22 = 4

21 = 2

20 = 1

Decimal

b = 6

0

1

1

0

6

b << 1

1

1

0

0

12

b >> 1

0

0

1

1

3

Para mostrar un ejemplo de operaciones bit a bit de and, or y not, creamos una tabla con los bits individuales. Las operaciones se aplican a un número con representación binaria en una máscara de bits:

Expresión

23 = 8

22 = 4

21 = 2

20 = 1

Decimal

bits = 6

0

1

1

0

6

mask = 5

0

1

0

1

5

bits & mask

0

1

0

0

4

bits | mask

0

1

1

1

7

bits ^ mask

0

0

1

1

3

El operador bit a bit not invierte una secuencia de bits. Ahí, cada 1 se convierte en 0 y viceversa. Además, el signo de la cifra también se invierte:

Expresión

23 = 8

22 = 4

21 = 2

20 = 1

Decimal

b = 6

0

1

1

0

6

~ b

1

0

0

1

-7

Operadores de asignación

Las asignaciones son unas de las instrucciones básicas presentes en la mayoría de los lenguajes de programación. Los operadores de asignación de Python vinculan un valor a un nombre de variable. Además de la orden de asignación, existe un nuevo operador “morsa”, que permite asignar dentro de una expresión. También hay una serie de órdenes de asignación ampliadas que combinan una asignación con otra operación:

Operador Significado Función Ejemplo
= Orden de asignación Sin correspondencia directa name = 'Walther'
:= Expresión de asignación (operador morsa) Sin correspondencia directa [ half for x in range(10) if (half := x / 2) < 5 ]
+= Asignación de suma ampliada iadd(a, b) x = 1; x += 4; assert x == 5

Python reconoce operadores de asignación ampliada para las operaciones aritméticas y bit a bit. Te mostramos el patrón general de la asignación de concatenación ampliada. En primer lugar, un código que se añade a un string existente:

name = 'Walther'
name = name + 'White'
assert name == 'WaltherWhite'

Un ejemplo equivalente con el operador de concatenación ampliado de Python “+=”. Consigue lo mismo pero el código es más corto y más informativo:

name  = 'Walther'
name += 'White'
assert name == 'WaltherWhite'

Operadores de identidad

El operador is de Python prueba si dos variables se refieren al mismo objeto en memoria. La identidad de los objetos contrasta con su igualdad, que se comprueba mediante el operador de comparación de Python “==”. El is de Python corresponde en JavaScript a un operador de igualdad estricta “===”. Además, Python reconoce la prueba de identidad negada con el operador is not:

Operador Significado Función Ejemplo
is Prueba de identidad is_(a, b) a = 42; b = a; assert a is b
is not Prueba de identidad negada is_not(a, b) assert [42] is not [42]

Pongamos algunos ejemplos. Creamos en la memoria una referencia a un objeto. Luego creamos otra referencia como alias. Ambas variables señalan el mismo objeto de la memoria, por lo que el operador is devuelve “True”:

# assign value to name
a = [42]
# reference existing object
b = a
# if this holds
assert a is b
# so will this
assert a == b

Aquí creamos dos referencias a objetos independientes en la memoria. Aunque los objetos son los mismos, son distintos. En consecuencia, el operador is devuelve “Falso”:

# assign the same value to different names
a = [42]
b = [42]
# `a`, `b` are two different objects
assert a is not b
# that contain the same value
assert a == b

Operador condicional

El operador condicional de Python es otro uso de la palabra clave if else. Se suele utilizar para distinguir entre dos posibles valores en las asignaciones. Dado que el operador condicional combina una condición y dos expresiones, también se conoce como operador ternario.

Operador Significado Función Ejemplo
... if ... else ... Expresión condicional Sin correlación directa name = 'Jim' if age == 42 else 'Jack'

A continuación, examinamos un ejemplo de uso de la asignación if else en Python. Este código establece Celsius o Fahrenheit como unidad de medición de temperatura en función del sistema de medición elegido:

if system == 'metric':
    unit = 'C'
else:
    unit = 'F'

Al aplicar el operador condicional, se simplifica el código en una única asignación:

unit = 'C' if system == 'metric' else 'F'

Operadores de conjunto en Python

Además de strings, tuples, listas y diccionarios, Python admite por defecto los conjuntos como tipo de datos compuesto. Los operadores sobrecargados se definen para las operaciones de conjunto habituales:

Operador Significado Función Ejemplo    
& Formar la unión de dos conjuntos and_(a, b) {'a', 'b'} & {'a', 'c'} == {'a'}    
    Crear la intersección de dos conjuntos or_(a, b) {'a', 'b'} {'a', 'c'} == {'a', 'c', 'b'}
^ Crear una diferencia simétrica entre dos conjuntos xor(a, b) {'a', 'b'} ^ {'a', 'c'} == {'c', 'b'}    
- Formar la diferencia de dos conjuntos sub(a, b) {'a', 'b'} - {'a'} == {'b'}    
> Comprobar si el conjunto es un verdadero superconjunto gt(a, b) assert {'a', 'b'} > {'a'}    
>= Comprobar si un conjunto es un superconjunto ge(a, b) assert {'a'} >= {'a'}    
< Comprobar si un conjunto es un verdadero subconjunto lt(a, b) assert {'a'} < {'a', 'b'}    
<= Comprobar si un conjunto es un subconjunto le(a, b) assert {'a'} <= {'a'}    

Operadores de membresía de Python

Los operadores de membresía de Python in y not in declaran si una colección contiene un objeto.

Operador

Significado

Función

Ejemplo

in

Comprueba si un iterable contiene un objeto

contains(a, b)

'y' in 'Python'

not in

Negación del operador in

not contains(a, b)

'x' not in 'Python'

Los operadores de membresía funcionan con iterables y recurren a la comprobación de igualdad para determinar si el objeto meta está incluido en la colección:

'Py' in 'Python'
'Px' not in 'Python'
'Jack' in ['Jim', 'Jack']

Al aplicar el operador in, te ahorras tener que escribir el código de esta manera:

def my_in(target, collection):
    for element in collection:
        if element == target:
            return True
    return False
# test
word = 'Python'
letter = 'y'
assert (my_in(letter, word)) == (letter in word)

Operador de concatenación

En Python, el operador de concatenación se utiliza para concatenar secuencias del mismo tipo. El signo más se utiliza como símbolo de operador.

Operador Significado Función Ejemplo
+ Encadena dos secuencias add(a, b) ['Jim'] + ['Jack', 'John']

Veamos un par de ejemplos. Concatenamos dos strings, dos listas y dos tuple:

assert "Walter" + "White" == 'WalterWhite'
assert ['a', 'b'] + ['c'] == ['a', 'b', 'c']
assert ('q', 'r') + ('s', 't') == ('q', 'r', 's', 't')

Python se usa como lenguaje de programación de Internet. En este contexto, el operador de concatenación se usa para ensamblar etiquetas HTML:

site_title = 'Welcome'
print('<h1>' + site_title + '</h1>')

Si comparamos Python con PHP, observamos que los operadores de concatenación son distintos. PHP utiliza el punto “.” como símbolo. El mismo ejemplo en PHP:

$siteTitle = 'Welcome';
echo '<h1>' . $siteTitle . '</h1>';

Operadores índex y slicing

El operador índex de Python sirve para extraer un elemento determinado de una colección. Con el operador de slicing, puedes extraer una subsecuencia.

Operador Significado Función Ejemplo
iterable[index] Devuelve el elemento de un iterable situado bajo el índice getitem(iterable, index) 'Python'[1] == 'y'
sequence[start:stop:step] Devuelve un trozo de una secuencia getitem(iterable, slice(start, stop, step)) 'Python'[0:1] == 'Py', 'Python'[0:-1:2] == 'Pto'

Los operadores de índex y slicing recurren internamente al método dunder __getitem__(). Se activan con un índice numérico o un objeto slice:

names = ['Jim', 'Jack', 'John']
names[0] == names.__getitem__(0)
names[0:2] == names.__getitem__(slice(0, 2))

El operador slice es práctico porque permite extraer una subsecuencia sin aplicar un Python for Loop ni un Python while loop. De esta manera, al programar, nos ahorramos tener que escribir el siguiente código:

word = 'Python'
start, stop, step = 0, 5, 2
index, substring = start, ''
while index in range(start, stop, step):
    substring += word[index]
    index += step
# test
assert substring == word[start:stop:step]