Apéndice C — Operadores.

Objetivo. Explicar los operadores aritméticos, relacionales y lógicos, así como mostrar su uso con varios ejemplos.

C.1 Operadores aritméticos

Para los tipos numéricos básicos, existen operaciones aritméticas que se pueden aplicar sobre ellos. Estas operaciones están organizadas como se muestra en la siguiente tabla:

Categoría Operadores
Exponenciación **
Multiplicación *,/,//,%
Adición +,-

Veamos algunos ejemplos:

# Suma
suma = 1 + 2

# Imprimimos el resultado y el tipo
print(suma, type(suma))
3 <class 'int'>
# Resta
resta = 5 - 32

# Imprimimos el resultado y el tipo
print(resta, type(resta))
-27 <class 'int'>
# Multiplicación
multiplicacion = 3 * 3

# Imprimimos el resultado y el tipo
print(multiplicacion, type(multiplicacion))
9 <class 'int'>
# División
division = 3 / 2

# Imprimimos el resultado y el tipo
print(division, type(division))
1.5 <class 'float'>
# División entera: divide los números y elimina la parte decimal
div_entera = 50 // 3

# Imprimimos el resultado y el tipo
print(div_entera, type(div_entera))
16 <class 'int'>
# Módulo: divide los números y regresa el residuo.
modulo = 50 % 3

# Imprimimos el resultado y el tipo
print(modulo, type(modulo))
2 <class 'int'>
# Potencia usando un entero
potencia = 9**2 # 9 al cuadrado

# Imprimimos el resultado y el tipo
print(potencia, type(potencia))
81 <class 'int'>
# Potencia usando un número decimal
potencia = 81**0.5 # raíz cuadrada de 81

# Imprimimos el resultado y el tipo
print(potencia, type(potencia))
9.0 <class 'float'>
# Potencia usando un número decimal
potencia = 2**(0.35) # 2 elevado a la potencia 0.35

# Imprimimos el resultado y el tipo
print(potencia, type(potencia))
1.2745606273192622 <class 'float'>

C.2 Precedencia.

La aplicación de los operadores tiene cierta precedencia que está definida en cada implementación del lenguaje de programación. La siguiente tabla muestra el orden en que se aplicarán los operadores.

Nivel Categoría Operadores
7 exponenciación **
6 multiplicación *,/,//,%
5 adición +,-
4 relacional ==,!=,<=,>=,>,<
3 lógicos not
2 lógicos and
1 lógicos or

Como se puede ver, siempre se aplican primero los operadores aritméticos (niveles 7, 6, y 5), luego los relacionales (nivel 4) y finalmente los lógicos (3, 2 y 1).

Más acerca de este tema se puede ver aquí: Operator precedence.

A continuación se muestran ejemplos de operaciones aritméticas en donde se resalta esta precedencia:

# Precedencia de operaciones: primero se realiza la multiplicación
1 + 2 * 3 + 4
11
# Es posible usar paréntesis para modificar la precedencia: primero la suma
(1 + 2) * (3 + 4)
21
# Primero se realiza la exponenciación
3**2/2
4.5

C.3 Operaciones entre tipos diferentes

Es posible combinar operaciones entre tipos de números diferentes. Lo que Python hará es promover cada número al tipo más sofisticado, siendo el orden de sofisticación, de menos a más, como sigue: int, float, complex.

# Operación entre enteros
a = 2 * 3
print(a, type(a))
6 <class 'int'>
# Operación entre entero y flotante
a = 2 * 3.0
print(a, type(a))
6.0 <class 'float'>
# Operación entre entero y complejo
a = 2 * (1 + 3j)
print(a, type(a))
(2+6j) <class 'complex'>
# Operación entre flotante y complejo
a = 2.0 * (1 + 3j)
print(a, type(a))
(2+6j) <class 'complex'>
# División entre enteros que da como resultado un flotante
a = 2/3
print(a, type(a))
0.6666666666666666 <class 'float'>

C.4 Operadores de asignación

Existen varios operadores para realizar asignaciones:

Operador Operación Equivalencia
+= b += a b = b + a
-= b -= a b = b - a
*= b *= a b = b * a
/= b /= a b = b / a
//= b //= a b = b // a
%= b %= a b = b % a
**= b **= a b = b ** a

La forma de uso de estos operadores se muestra en los siguientes ejemplos:

a = 1.0 
b = 1.0
b += a  
print(b)
2.0
a =  4
b = 16
b -= a  
print(b)
12
a = 2
b = 12
b *= a  
print(b)
24
a = 3
b = 50
b /= a 
print(b)
16.666666666666668
a = 3
b = 50
b //= a 
print(b)
16
a = 3
b = 50
b %= a
print(b)
2
a = 2
b = 3
b **= a 
print(b)
9

C.5 Operadores relacionales

Cuando se aplica un operador relacional a dos expresiones, se realiza una comparación entre dichas expresiones y se obtiene como resultado un tipo lógico (bool): True o False.

Los operadores relacionales que están definidos son:

Operador Operación Significado
== A == B ¿Es A igual a B?
!= A != B ¿Es A diferente de B?
> A > B ¿Es A mayor que B?
>= A >= B ¿Es A mayor o igual a B?
> A < B ¿Es A menor que B?
<= A >= B ¿Es A menor o igual a B?

A continuación se muestran algunos ejemplos:

# ¿Es 35 mayor que 562?
35 > 562 
False
# ¿Es 32 mayor o igual que 21?
32 >= 21 
True
# ¿Es 12 menor que 34?
12 < 34 
True
# ¿Es 12 menor o igual que 25?
12 <= 25 
True
# ¿Es 1 igual a 2?
1 == 2 
False
# ¿Es 1 diferente de 2?
1 != 2
True
# Se pueden comparar otros tipos de datos
'aaa' == 'aaaA' 
False
# La comparación se puede hacer con el resultado de expresiones
5 > len('5')
True

C.6 Operaciones lógicas.

Los operadores lógicos que se pueden usar son:

Operador Uso Resultado
not not A Invierte el resultado de A
and A and B True si A y B son True; False en otro caso
or A or B False si A y B son False; True en otro caso

Veamos algunos ejemplos.

C.6.1 and

Para que el resultado sea verdadero, se deben cumplir las dos expresiones que se encuentran a la derecha e izquierda del and. Si una de ellas no se cumple, el resultado será falso.

(5 < 32) and (63 > 32) 
True

Debido a la precedencia de operadores (véase Sección C.2), no son necesarios los paréntesis en la operaciones relacionales de la expresión anterior, por lo que es posible escribir:

5 < 32 and 63 > 32
True

Aunque a veces el uso de paréntesis hace la lectura del código más clara:

(2.32 < 21) and (23 > 63)
False

C.6.2 or

Para que el resultado sea verdadero, se deben cumplir una de las dos expresiones que se encuentran a la derecha e izquierda del ‘or’. Si una de ellas se cumple, el resultado será verdadero.

(32 == 21) or (5 < 31)
True

Para que el resultado sea falso, ambas expresiones deben ser falsas.

(32 == 21) or (31 < 5) 
False

C.6.3 not

Este operador es usado para obtener el valor Booleano opuesto al valor actual de una variable. Se conoce como el operador de negación.

# Invierte el resultado de la expresión
not True
False
a = 32 != 32
print(a)
print(not a)
False
True

C.7 Operador is

Este operador permite comprobar si dos objetos son el mismo. Por ejemplo:

a = 1
b = a

# Preguntamos si 'b' representa el mismo objeto que 'a'
print('¿b es a?', b is a)

# Imprimimos sus identificadores en memoria
print('id(a) = ', id(a))
print('id(b) = ', id(b))
¿b es a? True
id(a) =  140714900202408
id(b) =  140714900202408

Podemos hacer la pregunta inversa agregando el operador not:

# Preguntamos si 'b' NO representa el mismo objeto que 'a'
print('¿b NO es a?', b is not a)

# Imprimimos sus identificadores en memoria
print('id(a) = ', id(a))
print('id(b) = ', id(b))
¿b NO es a? False
id(a) =  140714900202408
id(b) =  140714900202408

Finalmente, si modificamos b tenemos:

b = 5.0
print('¿b es a?', b is a)
print('¿b NO es a?', b is not a)
print('id(a) = ', id(a))
print('id(b) = ', id(b))
¿b es a? False
¿b NO es a? True
id(a) =  140714900202408
id(b) =  2288439605360

C.8 Comparación entre números flotantes.

La comparación entre números de tipo flotante debe realizarse con cuidado, veamos el siguiente ejemplo:

(0.4 - 0.3) == 0.1
False

El cálculo a mano de (0.4 - 0.3) da como resultado 0.1, pero en una computadora este cálculo es aproximado y depende de las características del hardware (exponente, mantisa, base, etcétera), véase Floating-Point Arithmetic para más información.

En Python el resultado de la operación (0.4 - 0.3) es diferente de 0.1, veamos:

print(0.4 - 0.3)
0.10000000000000003

Python ofrece herramientas que permiten realizar una mejor comparación entre números de tipo flotante. Por ejemplo la biblioteca math contiene la función isclose(a, b) en donde se puede definir una tolerancia mínima para que las dos expresiones, a y b se consideren iguales (cercanas), por ejemplo:

# Importamos el módulo math
import math

# Utilizamos la función `isclose()` de math para comparar dos números flotantes
math.isclose((0.4 - 0.3), 0.1)
True

Se recomienda revisar el manual de math.isclose() y el de numpy.isclose() para comparación de arreglos con elementos de tipo flotante.

C.9 Fuertemente tipado.

Python es fuertemente tipado, lo que significa que el tipo de un objeto no puede cambiar repentinamente, se debe realizar una conversión explícita si se desea cambiar el tipo de un objeto.

Esta característica también impide que se realizen operaciones entre tipos no compatibles.

Veamos unos ejemplos:

# Definimos tres números
real   = 220.0  
entero = 284
complejo = 1+1j
entero + real # Los tipos son compatibles
504.0
real + complejo # Los tipos son compatibles
(221+1j)
entero + complejo # Los tipos son compatibles
(285+1j)

Un tipo lógico se puede comportar como un entero, un flotante o un complejo, los tipos son compatibles. Para que un valor numérico sea considerado verdadero, debe ser equivalente a 1.

Veamos los siguientes ejemplos:

lógico = True 
print(lógico == 1)
print(lógico == 1.0)
print(lógico == 1.0 + 0.0j)
True
True
True
print(lógico == 5)
print(lógico == 1.1)
print(lógico == 1.0 + 0.1j)
False
False
False

Entonces podemos realizar operaciones aritméticas entre lógicos, enteros, flotantes y complejos:

lógico + entero # Los tipos son compatibles
285
lógico + real # Los tipos son compatibles
221.0
lógico + complejo # Los tipos son compatibles
(2+1j)

Pero hay tipos que no son compatibles, por ejemplo:

cadena = 'El resultado es igual a '
cadena + real  # Los tipos no son compatibles
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[55], line 2
      1 cadena = 'El resultado es igual a '
----> 2 cadena + real  # Los tipos no son compatibles

TypeError: can only concatenate str (not "float") to str

Sin embargo es posible hacer una conversión explícita, por ejemplo:

cadena + str(real)
'El resultado es igual a 220.0'