Truthy/Falsy e is vs ==
Al finalizar este tema
En Python, sabrá qué valores se evalúan como True/False en una instrucción condicional y podrá distinguir y utilizar correctamente is y ==.
Truthy y Falsy
La instrucción if de Python no solo acepta True/False. Cualquier valor puede utilizarse como condición:
if "hello": print("Ejecutado") # ¡Ejecutado!
if 0: print("No se ejecuta") # No se ejecutaPython divide todos los valores en Truthy (tratados como verdaderos) y Falsy (tratados como falsos).
Valores Falsy — memorízalos y listo
Los valores Falsy están definidos. Todo lo demás es Truthy:
# Estos valores son Falsy (se evalúan como False)FalseNone0 # Entero 00.0 # Número real 0"" # Cadena vacía[] # Lista vacía{} # Diccionario vacíoset() # Conjunto vacío# Comprobaciónvalues = [False, None, 0, 0.0, "", [], {}, set()]for v in values: print(f"{str(v):10} → {bool(v)}")# False → False# None → False# 0 → False# 0.0 → False# → False# [] → False# {} → False# set() → FalseRegla fundamental: "Vacío o cero es Falsy". Solo recuerda esto.
Patrón práctico — Verificación de valores vacíos
Al utilizar Truthy/Falsy, el código se vuelve más conciso:
# Comprueba si la lista está vacíaitems = []
# No es necesario escribirlo asíif len(items) > 0: print("Hay elementos")
# Basta con escribirlo asíif items: print("Hay elementos")# Comprueba si la cadena está vacíaname = ""
if name: print(f"Hola, {name}")else: print("Introduce un nombre")# Comprobación de None y valor predeterminadodef greet(name=None): name = name or "visitante" return f"Hola, {name}"
print(greet()) # "Hola, visitante"print(greet("Carlos")) # "Hola, Carlos"or devuelve el lado derecho si el lado izquierdo es Falsy. Se usa frecuentemente como patrón de valor predeterminado.
== — ¿Son iguales los valores?
== compara si dos valores son iguales:
a = [1, 2, 3]b = [1, 2, 3]
print(a == b) # True: el contenido es igualAunque las dos listas son objetos distintos, como contienen los mismos valores, == es igual a True.
print(1 == 1.0) # True: los valores numéricos son igualesprint("abc" == "abc") # Trueprint([1] == [1]) # Trueis — ¿Son el mismo objeto?
is compara si dos variables apuntan al mismo objeto en la memoria:
a = [1, 2, 3]b = [1, 2, 3]c = a
print(a == b) # True: los valores son igualesprint(a is b) # False: son objetos diferentesprint(a is c) # True: apuntan al mismo objetoa y b tienen el mismo contenido, pero son objetos de lista diferentes. c = a apunta a la misma lista, por lo que is es igual a True.
# Puede comprobarse con id()print(id(a)) # 140234567890print(id(b)) # 140234567920 (dirección diferente)print(id(c)) # 140234567890 (misma dirección que a)Comparación con None: Por qué usar is
result = None
# ✅ Forma correctaif result is None: print("Sin resultados")
# ❌ Forma no recomendadaif result == None: print("Sin resultados")None es un único objeto en todo Python. Al compararlo con is, se verifica directamente "¿es este el objeto None?".
== puede comportarse de manera inesperada si la clase sobrescribe el método __eq__:
class Tricky: def __eq__(self, other): return True # True al compararlo con cualquier valor
t = Tricky()print(t == None) # True: ¡peligro!print(t is None) # False: seguroEl PEP 8 (la guía de estilo oficial de Python) también especifica que se debe usar is para las comparaciones con None.
Trampa del almacenamiento en caché de enteros
a = 256b = 256print(a is b) # True: CPython guarda de antemano -5~256 en caché
a = 257b = 257print(a is b) # False: fuera del intervalo se crean objetos distintosCPython crea y reutiliza previamente los enteros pequeños (-5 a 256). Dentro de este rango, is es True, pero fuera de él, False. Esta es la razón por la que no se debe usar is para la comparación de valores. is solo se utiliza para las comparaciones de None, True y False.
# En las cadenas ocurre un fenómeno similara = "hello"b = "hello"print(a is b) # True: se aplica interning
a = "hello world!"b = "hello world!"print(a is b) # False: no se aplica interning al incluir espacios y símbolosValores predeterminados de parámetros de función y None
# ❌ Patrón peligrosodef add_item(item, items=[]): items.append(item) return items
print(add_item("a")) # ["a"]print(add_item("b")) # ["a", "b"] — ¡conserva el resultado de la llamada anterior!
# ✅ Patrón segurodef add_item(item, items=None): if items is None: items = [] items.append(item) return itemsSi se utiliza un objeto mutable (lista, diccionario) como valor predeterminado, todas las llamadas compartirán el mismo objeto. Usar None como valor predeterminado y crear un nuevo objeto dentro de la función es el patrón estándar en Python.
Uso de bool() y valores "Truthy/Falsy"
# Validación concisa de valores vacíosdata = {"name": "Carlos", "email": "", "phone": None}
# ❌ Largo y repetitivoif data["name"] is not None and data["name"] != "": print("Hay un nombre")
# ✅ Uso de Truthy/Falsyif data["name"]: print("Hay un nombre")
# Filtra solo los valores válidosvalues = [0, "", None, "hello", [], [1, 2], False, 42]valid = list(filter(None, values))print(valid) # ["hello", [1, 2], 42]filter(None, iterable) elimina todos los valores falsy. Es un patrón comúnmente utilizado en la limpieza de datos.
Resumen
| Comparación | Significado | Cuándo usarlo |
|---|---|---|
== | ¿Son iguales los valores? | Para comparaciones generales de valores |
is | ¿Son el mismo objeto? | Para comparar None, True, False |
!= | ¿Son diferentes los valores? | Para verificar inconsistencias generales |
is not | ¿Son objetos diferentes? | Para is not None |
# Recuerda estos patronesif x is None: # Comprueba Noneif x is not None: # Comprueba que no sea Noneif items: # Comprueba que no esté vacío (Truthy)if not items: # Comprueba que esté vacío (Falsy)any() y all() — Aprovechamiento de valores truthy en colecciones
scores = [85, 92, 0, 78, 95]
print(any(scores)) # True: hay al menos un valor Truthy distinto de 0print(all(scores)) # False: 0 es Falsy
# Con expresiones condicionalesprint(any(s >= 90 for s in scores)) # True: ¿hay alguno mayor o igual que 90?print(all(s >= 60 for s in scores)) # False: ¿son todos mayores o iguales que 60?any() y all() utilizan internamente la evaluación de verdad/falsedad (Truthy/Falsy). Son útiles para expresar condiciones de manera concisa.
Uso de evaluación de cortocircuito (Short-circuit)
# or: devuelve el primer Truthy (o el último valor si no hay ninguno)name = user_input or "nombre_predeterminado"
# and: devuelve el primer Falsy (o el último valor si no hay ninguno)result = data and data[0] # Si data está vacío devuelve []; si no, el primer elementoor y and no devuelven un valor booleano, sino el valor en el momento en que se detiene la evaluación de verdad/falsedad. Se utilizan frecuentemente para establecer valores predeterminados o patrones de acceso seguro.
No comprender la diferencia entre == y is puede generar errores difíciles de detectar. En particular, el hábito de usar is en lugar de == al comparar con None es una práctica fundamental para la calidad del código en Python.