Operadores y expresiones
Aritmética, comparaciones, lógica booleana y el orden exacto en que Python evalúa cada símbolo
Una expresión combina valores y operadores para producir un resultado nuevo. En esta lección dominas la aritmética de Python, las comparaciones, la lógica con cortocircuito, la diferencia entre `is` y `==`, la precedencia y los operadores que además asignan, como `+=` y `:=`.
- Calcular con los operadores aritméticos y explicar la diferencia entre `/`, `//` y `%`
- Construir condiciones con comparaciones encadenadas y operadores lógicos
- Predecir el resultado de una expresión aplicando la precedencia
- Distinguir igualdad de identidad y saber cuándo usar `==` y cuándo `is`
- Usar asignación aumentada y el operador morsa sin perder legibilidad
Antes necesitas: Variables y tipos de datos
En esta lección
- ¿Qué es un operador y qué es una expresión?
- ¿Para qué sirven?
- ¿Cómo funciona por dentro? Precedencia y asociatividad
- Sintaxis: los operadores aritméticos
- Comparaciones: preguntas que devuelven bool
- Operadores lógicos y cortocircuito
- Identidad frente a igualdad: `is` y `==`
- Asignación aumentada y operador morsa
- Ejemplo básico: dividir una cuenta
- Ejemplo intermedio: promedio ponderado
- Caso práctico: repartir fotos en paquetes
- Visualización: cómo se reparte la cuenta
- Errores comunes
- Buenas prácticas
- Ejercicios
- Soluciones explicadas
- Resumen
- Evaluación
Ya sabes guardar valores. El siguiente paso es transformarlos: sumar dos precios, comprobar si una nota llega al mínimo, decidir si un cliente cumple dos requisitos. Todo eso se escribe con operadores, los símbolos que conectan valores y producen un resultado nuevo.
Esta lección es corta en teoría y larga en consecuencias. Un error de precedencia o un = donde iba == puede cambiar por completo el comportamiento de un programa que parece correcto a simple vista.
¿Qué es un operador y qué es una expresión?
Un operador es un símbolo que opera sobre uno o más valores llamados operandos. En 7 + 2, el operador es + y los operandos son 7 y 2. Una expresión combina valores, nombres y operadores y se reduce a un único valor: precio * cantidad, not activo, 0 < nota <= 20.
Piensa en los operadores como los verbos de la frase: los valores son sustantivos y el operador dice qué se hace con ellos. a + b no es una orden que desaparece: es una expresión que devuelve un valor que puedes imprimir, guardar o combinar con otro.
¿Para qué sirven?
Casi todo lo que hace un programa útil pasa por un operador. Estos son los usos que verás una y otra vez:
- Calcular totales:
subtotal + igv,precio * cantidad,total / meses. - Validar datos:
0 <= nota <= 20,stock > 0,correo != "". - Combinar requisitos:
edad >= 18 and tiene_dni. - Acumular:
total += ventadentro de un bucle. - Machine Learning: normalizar es
(x - media) / desviacion; una predicción binaria se decide conprobabilidad >= 0.5.
¿Cómo funciona por dentro? Precedencia y asociatividad
Python analiza la expresión, construye un árbol donde cada operador tiene como hijos sus operandos y lo evalúa de abajo hacia arriba. El orden lo decide la precedencia: cuanto más arriba está un operador en la tabla, antes se aplica.
| Prioridad | Operadores | Ejemplo | Resultado |
|---|---|---|---|
| 1 (mayor) | ** | 2 ** 3 ** 2 | 512, porque asocia a la derecha |
| 2 | *, /, //, % | 7 // 2 * 3 | 9 |
| 3 | +, - | 2 + 3 - 1 | 4 |
| 4 | <, <=, >, >=, ==, != | 0 < 5 <= 5 | True |
| 5 | not | not True | False |
| 6 | and | True and False | False |
| 7 (menor) | or | False or True | True |
Cuando dos operadores tienen la misma prioridad, casi todos asocian por la izquierda: 100 / 10 / 2 es (100 / 10) / 2, o sea 5.0. La potencia asocia por la derecha: 2 ** 3 ** 2 es 2 ** 9, no 8 ** 2. Ante la duda, escribe paréntesis.
Sintaxis: los operadores aritméticos
Son siete y cada uno responde una pregunta distinta. +, - y * se comportan como esperas; los otros cuatro merecen atención.
print(7 / 2)
print(7 // 2)
print(7 % 2)
print(2 ** 10)
print(-7 // 2, -7 % 2)7 / 2da3.5: la división normal siempre devuelvefloat.7 // 2da3: división entera, descarta la parte decimal.7 % 2da1: el resto de la división entera.2 ** 10da1024: potencia.-7 // 2da-4y-7 % 2da1: con negativos,//redondea hacia menos infinito y el resto conserva el signo del divisor.
La relación entre // y % es útil para recordar: a == (a // b) * b + (a % b). Con a = 47 y b = 6, 47 // 6 es 7, 47 % 6 es 5, y 7 * 6 + 5 vuelve a dar 47. Esa pareja sirve para repartir unidades en paquetes y saber cuántas sobran.
Comparaciones: preguntas que devuelven bool
Los operadores de comparación (==, !=, <, <=, >, >=) comparan dos valores y producen True o False. Python permite encadenarlos, y la cadena se lee como una conjunción: 0 < nota <= 20 equivale a 0 < nota and nota <= 20, pero evalúa nota una sola vez.
print(1 == 1.0)
print("a" < "b")
print(0 < 16 <= 20)
print(10 != 10)1 == 1.0 es True: la igualdad compara valores numéricos, no tipos. "a" < "b" compara códigos de caracteres y da True. 0 < 16 <= 20 se lee como una sola pregunta. 10 != 10 es False. Nunca escribas x = 5 en una comparación: = asigna y == compara.
Operadores lógicos y cortocircuito
and, or y not combinan valores lógicos. and es verdadero solo si ambos lados lo son; or lo es si al menos uno lo es; not invierte. Lo importante ocurre con el cortocircuito: si el lado izquierdo ya decide el resultado, Python no evalúa el derecho.
a = 10
b = 0
print(b != 0 and a / b > 2)
print(b == 0 or a / b > 2)
print(not b)La línea 4 imprime False sin lanzar ZeroDivisionError: como b != 0 es falso, and no mira la división. La línea 5 también evita el error porque b == 0 ya decide. La línea 6 imprime True: 0 es falso y not lo invierte. Ese orden es la base de las guardas que protegen cálculos peligrosos.
Identidad frente a igualdad: `is` y `==`
== pregunta «¿valen lo mismo?». is pregunta «¿son exactamente el mismo objeto en memoria?». Para enteros pequeños y cadenas cortas, Python reutiliza objetos y is puede dar True por casualidad; con listas construidas por separado, no.
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b)
print(a is b)
print(a is c)La salida es True, False, True. a y b tienen el mismo contenido pero son listas distintas; c es otra etiqueta del mismo objeto que a. Usa == para valores y reserva is para None, True y False. if x is None es correcto; if x == None funciona pero se considera mal estilo.
Asignación aumentada y operador morsa
total += venta equivale a total = total + venta, pero evalúa el destino una sola vez y comunica mejor la idea de acumular. Existen -=, *=, /=, //=, %= y **=. Con textos, += concatena; con listas, extiende.
stock = 12
stock -= 5
precio = 45.5
precio *= 2
print(stock, precio)stock pasa de 12 a 7 y precio de 45.5 a 91.0. Cada operador trabaja con los tipos de sus operandos: int menos int da int, y float por int da float. El operador morsa := (Python 3.8+) asigna dentro de una expresión y devuelve el valor, lo que evita calcular dos veces.
stock = 12
if (restante := stock - 5) > 5:
print(f"Quedan {restante} unidades")
print(restante * 2)restante se calcula una vez, se compara con 5 y queda disponible para el resto del bloque; no hace falta repetir stock - 5. Imprime Quedan 7 unidades y luego 14. El morsa es útil cuando necesitas el valor de una condición más de una vez; en expresiones largas, resta legibilidad.
Ejemplo básico: dividir una cuenta
Cuatro amigos pagan una cena de 187.5 soles y dejan 10 % de propina. El total se reparte en partes iguales. Cada operador interviene en un paso distinto:
cuenta = 187.5
personas = 4
propina = cuenta * 0.10
total = cuenta + propina
por_persona = total / personas
print(total, round(por_persona, 2))cuenta * 0.10 da 18.75; la suma da 206.25; la división entre 4 da 51.5625, que round reduce a 51.56. La multiplicación se ejecuta antes que la suma aunque no haya paréntesis, porque tiene mayor precedencia. Si solo se repartiera la cuenta sin propina, dividirías cuenta / personas y obtendrías 46.875.
Ejemplo intermedio: promedio ponderado
Un curso pondera prácticas al 30 %, examen al 30 % y proyecto al 40 %. Además, se aprueba solo si el promedio llega a 13 y el examen llega a 10. Aquí se combinan aritmética, comparación y lógica en dos líneas.
practicas = 16
examen = 14
proyecto = 18
promedio = practicas * 0.30 + examen * 0.30 + proyecto * 0.40
aprueba = promedio >= 13 and examen >= 10
print(f"Promedio: {promedio:.2f}")
print(f"¿Aprueba? {aprueba}")Los productos suman 4.8 + 4.2 + 7.2 = 16.2, que se muestra como 16.20. La condición evalúa primero promedio >= 13 (True), luego examen >= 10 (True), y and devuelve True. Si el examen fuera 9, el promedio no cambiaría pero aprueba sería False.
Caso práctico: repartir fotos en paquetes
Un cliente pide imprimir 47 fotos. Se venden en paquetes de 6 a 4.5 soles y las sueltas a 1.2 soles. Necesitas los paquetes completos, las fotos que sobran y el costo con IGV.
fotos = 47
por_paquete = 6
paquetes = fotos // por_paquete
sueltas = fotos % por_paquete
costo = paquetes * 4.5 + sueltas * 1.2
costo_final = round(costo * 1.18, 2)
print(f"Paquetes: {paquetes} | Sueltas: {sueltas}")
print(f"Total con IGV: S/ {costo_final}")47 // 6 es 7 y 47 % 6 es 5, porque 7 * 6 + 5 = 47. El costo base es 31.5 + 6.0 = 37.5; con IGV, 44.25. round(..., 2) corta el ruido de la coma flotante y la f-string final ya no necesita formato.
Visualización: cómo se reparte la cuenta
cuenta = 187.5personas = 4propina = cuenta * 0.10total = cuenta + propinapor_persona = round(total / personas, 2)print(por_persona)float 187.5 en cuenta.—
Avanza paso a paso: observa la línea resaltada, las variables y la salida.
Errores comunes
| Mensaje o síntoma | Por qué ocurre | Cómo se arregla |
|---|---|---|
ZeroDivisionError: division by zero | Dividiste entre 0, quizá con un dato vacío | Comprueba el divisor antes: if b != 0 |
TypeError: unsupported operand type(s) for +: 'int' and 'str' | Mezclaste número y texto en una operación | Convierte con int(), float() o str() |
TypeError: '>' not supported between instances of 'str' and 'int' | Comparaste un texto con un número | Convierte el texto o revisa de dónde viene el dato |
El resultado es False cuando esperabas True | Precedencia: not a and b se lee (not a) and b | Añade paréntesis explícitos |
SyntaxError: invalid syntax en una comparación | Escribiste = en lugar de == | Usa == para comparar |
nombre = "Ada"
print(nombre is "Ada") # puede ser True o Falsenombre = "Ada"
print(nombre == "Ada") # siempre True`is` compara identidad: si son el mismo objeto. El intérprete puede reutilizar cadenas cortas y hacer que `is` dé `True` por casualidad, pero no es una garantía del lenguaje. Para contenido, usa siempre `==`; reserva `is` para `None`, `True` y `False`.
Buenas prácticas
- Escribe paréntesis cuando mezcles
and,orynot: nadie debería recordar la tabla de precedencia. - Usa
==para valores eissolo conNone,TrueyFalse. - No compares
floatcon==; usaabs(a - b) < 1e-9. - Prefiere
//y%a conversiones cuando repartes unidades. - Evita cadenas largas sin nombres intermedios: se depuran peor.
- Deja espacios alrededor de los operadores:
a + b.
Ejercicios
Promedio ponderado con dos decimales
15 en prácticas, 18 en el examen y 12 en el proyecto. Las ponderaciones son 20 %, 50 % y 30 %. Calcula el promedio y muéstralo con dos decimales. Después comprueba si llega a 14 usando una comparación guardada en una variable booleana.Pista
Multiplica cada nota por su peso, suma los tres productos y aplica :.2f al imprimir. Para la comparación, guarda el resultado en una variable.
Minutos a horas y minutos
347 en total_minutos, calcula las horas completas y los minutos sobrantes, y muestra 347 minutos = 5 h 47 min. Resuélvelo solo con // y %.Pista
Una hora tiene 60 minutos: las horas completas son la división entera y el resto son los minutos sobrantes.
precio = 120 descuento = precio 0.10 total = precio - descuento print(total 100) print(total > 100 total < 120)
El descuento es un porcentaje del precio; las dos comparaciones deben cumplirse a la vez.
Soluciones explicadas
En el promedio ponderado, el error habitual es dividir entre 3 al final. Con pesos que ya suman 1 (0.20 + 0.50 + 0.30), no hay que dividir: cada nota ya está escalada. Si los pesos fueran enteros (20, 50, 30), dividirías entre 100. Comprueba que sumen 1 antes de confiar en el resultado.
En el ejercicio de minutos, // y % son complementarios: el cociente dice cuántas unidades completas caben y el resto, cuánto sobra. La misma idea convierte céntimos a soles o reparte artículos en cajas. No uses round aquí: redondear 5.78 a 6 horas sería incorrecto.
Resumen
- Un operador combina operandos y produce un valor; una expresión es la combinación completa.
/siempre devuelvefloat;//descarta decimales;%da el resto.- Con negativos,
//redondea hacia menos infinito y%conserva el signo del divisor. - Las comparaciones devuelven
booly se encadenan:0 <= nota <= 20. andyorcortocircuitan: el lado derecho solo se evalúa si hace falta.==compara valores;iscompara identidad y se reserva paraNone,TrueyFalse.- La precedencia va de
**aor; usa paréntesis ante la duda. +=acumula y:=asigna dentro de una expresión (3.8+).
Evaluación
¿Qué imprime print(7 // 2, 7 % 2)?
¿Cuál es el valor de 2 + 3 * 4 ** 2?
¿Qué devuelve 0 or "sin dato"?
¿Ya lo entendiste?
Márcala como completada para llevar tu progreso y desbloquear el siguiente paso de la ruta.