Saltar a contenido

1.3 · Operadores y expresiones

Objetivos. Al terminar este capítulo podrás: usar los operadores aritméticos, de comparación, lógicos, de identidad y de pertenencia; distinguir == de is; y escribir expresiones con la precedencia correcta.

Evidencia de logro. Dada una expresión, predecirás su resultado y explicarás el orden en que se evalúa, escribiendo una pequeña calculadora que decida según una comparación lógica.

Contexto y motivación

Los operadores permiten realizar operaciones con los datos: sumar, comparar, combinar condiciones y comprobar si un valor pertenece a una colección. Con ellos construimos expresiones, es decir, combinaciones de valores y operaciones que producen un resultado.

Muchos errores al empezar se deben a confundir un operador: usar = donde corresponde ==, creer que is compara valores u olvidar que 2 ** 3 + 1 se evalúa como (2**3) + 1. Este capítulo prepara los condicionales (1.4) y los bucles (1.5).

Vocabulario

Término Significado
Operador Símbolo que realiza una operación (+, ==, and, in…)
Operando Valor sobre el que actúa un operador
Expresión Combinación de operandos y operadores que produce un valor
Precedencia Orden en que se evalúan los operadores
Identidad Si dos nombres apuntan al mismo objeto (is)
Pertenencia Si un valor está dentro de una colección (in)

Prerrequisitos

Haber completado 1.2 · Variables y tipos y saber ejecutar un script con uv run python.

1. Operadores aritméticos

a = 10
b = 3

print(a + b)    # suma
print(a - b)    # resta
print(a * b)    # multiplicación
print(a / b)    # división SIEMPRE devuelve float
print(a // b)   # división entera (trunca hacia abajo)
print(a % b)    # resto de la división
print(a ** b)   # potencia

Salida esperada:

13
7
30
3.3333333333333335
3
1
1000

Conviene tener presentes estas diferencias:

  • a / b siempre devuelve un float, aunque sea exacto (10 / 2 → 5.0).
  • a // b es la división entera: se queda con el cociente entero, truncando hacia abajo.
  • a % b es el resto. Es la base de "¿es par?": n % 2 == 0.
  • a ** b es la potencia (10**3 = 1000).

División entera y resto con negativos

Con negativos, // trunca hacia abajo y % devuelve un resto con el signo del divisor:

print(7 // 2, -7 // 2)   # 3  -4
print(7 % 3, -7 % 3)     # 1   2

Salida esperada:

3 -4
1 2

No los memorices: entiende que -7 // 2 es -4 porque redondea hacia abajo (no hacia cero), y que -7 % 3 es 2 porque el resto cumple dividendo = divisor × cociente + resto. En este último caso, el cociente correspondiente es -7 // 3 = -3, así que -7 = 3*(-3) + 2. Lo importante es que con positivos el comportamiento es intuitivo.

Los decimales no son exactos

Un float guarda los decimales en binario y algunos, como 0.1, no se pueden representar exactamente. El resultado es un error diminuto:

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(round(0.1 + 0.2, 2) == 0.3)

Salida esperada:

0.30000000000000004
False
True

No es un fallo de Python: ocurre en casi todos los lenguajes. Para mostrar importes, redondea con round(valor, 2) (redondea a dos decimales); y no compares dos float con == sin redondear antes.

2. Operadores de asignación

= guarda un valor. Los operadores como += son abreviaturas que asignan y operan a la vez:

x = 10
x += 5    # x = x + 5
print(x)

x *= 2    # x = x * 2
x -= 3    # x = x - 3
x /= 4    # x = x / 4
print(x)

Salida esperada:

15
6.75

Existen +=, -=, *=, /=, //=, %=, **=. Son cómodos y evitan repetir la variable, pero no hagas magia con ellos: x /= 4 convierte x en float (por eso el resultado es 6.75, no 6).

3. Operadores de comparación

Devuelven un bool (True o False):

print(5 == 5)   # igualdad
print(5 != 3)   # distinto
print(5 > 3)    # mayor
print(5 <= 4)   # menor o igual
print(5 >= 5)   # mayor o igual

Salida esperada:

True
True
True
False
True

= vs ==

= asigna (x = 5); == compara (x == 5). Es el error número uno: escribir if x = 5: da un SyntaxError. Repite: signo de igual único = asignar; doble = comparar.

4. Operadores lógicos

Combinan booleanos (o valores truthy/falsy):

print(True and False)          # False
print(True or False)           # True
print(not True)                # False
print(3 > 2 and 1 < 2)         # True (ambas condiciones)

Salida esperada:

False
True
False
True
  • and: True solo si ambos son True.
  • or: True si al menos uno es True.
  • not: niega (not True → False).

Truthy y falsy

En un contexto booleano, Python considera falsy (como False) los valores 0, 0.0, "", [], (), {}, set() y None. Todo lo demás es truthy:

print(bool(0), bool(""), bool([]), bool(None))   # falsy
print(bool(-1), bool("a"))                        # truthy

Salida esperada:

False False False False
True True

Esto permitirá escribir if lista: (verdadero si la lista no está vacía) en lugar de if len(lista) > 0:. Es más idiomático.

5. Identidad y pertenencia

5.1 is vs == (identidad vs igualdad)

Esta es la confusión clásica. Para verla usamos listas: una colección de valores entre corchetes, como [1, 2, 3]. Las estudiarás en 1.6; aquí solo importa que una lista es un objeto que puede tener el mismo contenido que otra sin ser la misma.

a = [1, 2, 3]
b = a            # b apunta al MISMO objeto que a
c = [1, 2, 3]    # c es otro objeto, con el mismo contenido

print(a is b)     # mismo objeto  -> True
print(a is c)     # objetos distintos -> False
print(a == c)     # mismo valor    -> True

Salida esperada:

True
False
True
  • == compara valor (¿tienen el mismo contenido?).
  • is compara identidad (¿es el mismo objeto en memoria?).

Regla práctica: casi siempre quieres ==. Usa is solo para comparar con None (if x is None:) o con constantes de la librería. Nunca uses is para comparar números o cadenas: aunque a veces funcione por optimización interna, es frágil.

5.2 in y not in (pertenencia)

print("x" in "hola")      # ¿está el carácter?
print(2 in [1, 2, 3])     # ¿está en la lista?
print("clave" in {"clave": 1})  # ¿está la clave en el dict?
print("z" not in "hola")  # NO está

Salida esperada:

False
True
True
True

in funciona con cadenas, listas, tuplas, diccionarios (comprueba las claves) y conjuntos. Es una de las comprobaciones más usadas.

6. Precedencia de operadores

Python evalúa las expresiones en un orden fijo. Lo esencial para este curso:

  1. Paréntesis ( )
  2. Potencia **
  3. Unarios +x, -x, ~x
  4. Multiplicativos * / // %
  5. Aditivos + -
  6. Comparación, incluida la pertenencia y la identidad: == != < > <= >= in is
  7. not
  8. and
  9. or
print(2 + 3 * 4)          # 2 + (3*4) = 14
print((2 + 3) * 4)        # 20
print(2 ** 3 + 1)         # (2**3) + 1 = 9
print(not 2 > 1 and 3 > 2)  # not (2>1) and (3>2) -> False and True

Salida esperada:

14
20
9
False

Cuando dudes, usa paréntesis

La precedencia de not, and y or (en ese orden) es contraintuitiva. not 2 > 1 and 3 > 2 se evalúa (not (2>1)) and (3>2) → False and True → False. Si lo que querías era not (2 > 1 and 3 > 2), escríbelo con paréntesis. Nunca asumas: encierra la expresión entre ( ) cuando haya duda, y siempre usa paréntesis alrededor de cada comparación cuando combines con and/or.

7. Aplicación práctica: calculadora de propinas

total = 45.50
propina = 0.15          # 15 %

total_con_propina = total + total * propina
redondeo = round(total_con_propina, 2)

print("Total sin propina:", total)
print("Propina:", round(total * propina, 2))
print("Total con propina:", redondeo)
print("¿Cada uno de 2 paga más de 25?", redondeo / 2 > 25)

Salida esperada:

Total sin propina: 45.5
Propina: 6.83
Total con propina: 52.33
¿Cada uno de 2 paga más de 25? True

Fíjate en que hemos usado operadores aritméticos (*, +, /) y de comparación (>) en la misma línea, con round() para controlar los decimales. La expresión redondeo / 2 > 25 evalúa primero la división (por precedencia) y luego la comparación.

Errores frecuentes

  • Usar = en lugar de == en una condición.
  • Confundir is (identidad) con == (valor).
  • Creer que 10 / 2 da 5 (entero): da 5.0 (float).
  • Olvidar que // trunca hacia abajo con negativos.
  • No poner paréntesis al combinar and/or con comparaciones, y obtener un resultado inesperado.
  • Intentar comparar tipos incompatibles ("a" > 1) sin convertirlos antes.

Práctica de transferencia

  1. Escribe una expresión que diga si un número n es par y mayor que 10 (pista: n % 2 == 0 and n > 10).
  2. Dada una lista notas = [7, 9, 5], escribe y evalúa: ¿está el 9 en la lista? y ¿está el 10?.
  3. Con a = [1, 2] y b = a, predice y comprueba: a is b, a == b, y qué ocurre si haces b.append(3), que añade el 3 al final de la lista (¿cambia también a? ¿por qué?).
  4. Añade a la calculadora de propinas una condición: si el total supera 50 €, aplica un 10 % de descuento antes de la propina. Muestra los dos casos (total = 45.50 y total = 60.00). Pista: con la forma A if condición else B de 1.2, factor = 0.9 if total > 50 else 1.0.

Qué debes justificar: en el punto 3, la diferencia entre «mismo objeto» y «mismo contenido»; en el 4, en qué orden se evalúa tu expresión y dónde has puesto paréntesis para que no haya duda.

Producto evaluable

El mismo 02_variables_tipos.py de 1.2 · Variables y tipos, ampliado aquí con un apartado «Operadores» que:

  1. Use al menos un operador aritmético, uno de comparación, uno lógico, in e is.
  2. Calcule y muestre el resultado de la calculadora de propinas de los dos casos (con y sin descuento), con una interpretación breve del resultado.
  3. Compruebe la precedencia de una expresión con y sin paréntesis, y explique la diferencia.

Formato de entrega: script o cuaderno marimo ejecutado, con su salida real y la interpretación en comentarios (en un script) o en celdas Markdown (en un cuaderno).

Resumen y referencia rápida

Categoría Operadores Ejemplo
Aritméticos + - * / // % ** 7 // 2 → 3
Asignación = += -= *= /= //= %= **= x += 1
Comparación == != < <= > >= 5 >= 3 → True
Lógicos and or not True and False → False
Identidad is / is not a is None
Pertenencia in / not in 9 in notas
Precedencia ( ) > ** > * > + > comparación > not > and > or 2 + 3*4 → 14

Reglas prácticas: = asigna, == compara; usa == salvo para None; y paréntesis cuando combines lógicos con comparaciones.

Siguiente: 1.4 · Condicionales.