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]