El Zen de Python: los 19 principios que explican cómo piensa el lenguaje

El Zen de Python es la declaración de principios del lenguaje: una lista de aforismos que resumen cómo debería diseñarse y escribirse el código en Python. Los redactó Tim Peters, uno de los desarrolladores veteranos del proyecto, y desde 2004 están recogidos en la PEP 20, uno de los documentos oficiales de diseño del lenguaje.

Hay un detalle que suele pasarse por alto: la propia PEP 20 dice que Peters condensó los principios rectores de Python en veinte aforismos, «de los cuales solo diecinueve han sido escritos». El vigésimo nunca apareció, y esa ausencia terminó siendo parte de la broma.

Cómo mostrar el Zen de Python

Una de las curiosidades del lenguaje es que el Zen viene incluido en él. Basta con importarlo desde el intérprete:

import this

O ejecutarlo directamente desde la terminal:

python -m this

El módulo que lo imprime es, a su vez, otro chiste: el archivo this.py guarda el texto cifrado con ROT13 y lo descifra con una expresión enrevesada. Es decir, el código que predica la claridad incumple alegremente varios de sus propios principios.

El texto original

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

Los 19 principios, uno por uno

1. Beautiful is better than ugly

Lo bello es mejor que lo feo.

El código no debería limitarse a funcionar: también debería tener una estructura limpia y coherente. Buena parte de esa belleza está en los nombres.

# Funciona, pero no dice nada
x = [i for i in range(100) if i % 2 == 0]

# Comunica la intención
numeros_pares = [
    numero for numero in range(100)
    if numero % 2 == 0
]

Las dos versiones producen el mismo resultado, pero solo la segunda explica qué contiene la lista sin obligar a leer la condición.

2. Explicit is better than implicit

Lo explícito es mejor que lo implícito.

Python prefiere que el comportamiento de un programa se entienda leyéndolo, sin reglas ocultas que haya que adivinar.

# Implícito: ¿de dónde sale sqrt?
from math import *
resultado = sqrt(16)

# Explícito: el origen de cada nombre está a la vista
import math
resultado = math.sqrt(16)

El segundo bloque además evita que una importación con asterisco pise sin avisar una función que ya existía con ese nombre.

3. Simple is better than complex

Lo simple es mejor que lo complejo.

Si un problema se resuelve de forma directa, rara vez hace falta añadir maquinaria.

# Innecesariamente elaborado
from functools import reduce
total = reduce(lambda a, b: a + b, precios)

# Directo
total = sum(precios)

Ambos suman la misma lista, pero el segundo se entiende de un vistazo y no obliga a importar nada.

4. Complex is better than complicated

Lo complejo es mejor que lo complicado.

Algunos problemas son complejos por naturaleza: procesar pagos, autenticar usuarios o sincronizar información entre servidores exige cierta complejidad, y no hay forma de evitarla.

Lo que sí se puede evitar es la complicación: capas, indirecciones y abstracciones que no responden al problema, sino a la forma en que se fue escribiendo el código.

5. Flat is better than nested

Lo plano es mejor que lo anidado.

Cada nivel de anidamiento obliga a recordar una condición más. Salir temprano de la función suele leerse mejor.

if not usuario:
    return

if not usuario.activo:
    return

if not usuario.tiene_permiso:
    return

hacer_algo()

La alternativa —tres if encajados uno dentro de otro— deja la línea importante escondida al fondo de la escalera.

6. Sparse is better than dense

Lo espaciado es mejor que lo denso.

No se trata de añadir líneas en blanco, sino de no amontonar varios pasos conceptuales en una sola expresión.

# Denso: filtrado, acceso y formateo en un solo renglón
usuarios = [u["nombre"].strip().title() for u in datos if u.get("activo") and u.get("nombre")]

# Espaciado: cada paso se lee por separado
activos = [u for u in datos if u.get("activo") and u.get("nombre")]
usuarios = [u["nombre"].strip().title() for u in activos]

7. Readability counts

La legibilidad importa.

Este es el principio que sostiene a los demás. El código debería ser comprensible para quien lo herede, y también para uno mismo dentro de seis meses.

if edad >= 18:
    permitir_acceso()

La idea de fondo es sencilla: el código se escribe una vez, pero se lee muchas veces.

8. Special cases aren’t special enough to break the rules

Los casos especiales no son lo bastante especiales como para romper las reglas.

Una biblioteca o una API deberían comportarse de forma consistente. Cada excepción que se añade «solo para este caso» es una regla más que quien la use tendrá que memorizar.

9. Although practicality beats purity

Aunque la practicidad le gana a la pureza.

Los principios anteriores no son leyes. Si la solución teóricamente impecable resulta incómoda de usar o de mantener, la solución práctica gana.

Este aforismo es, en el fondo, el permiso explícito para no aplicar los otros de forma dogmática.

10. Errors should never pass silently

Los errores nunca deberían pasar silenciosamente.

Cuando algo falla, casi siempre queremos enterarnos. Tragarse las excepciones convierte un error visible en un comportamiento extraño que aparecerá mucho después y en otro sitio.

# Peligroso: oculta cualquier fallo, incluidos los que no esperábamos
try:
    procesar_datos()
except Exception:
    pass

Lo razonable es capturar solo el error que sabemos manejar y dejar constancia del resto:

import logging

try:
    procesar_datos()
except ValueError as error:
    logging.error("No se pudieron procesar los datos: %s", error)
    raise

11. Unless explicitly silenced

A menos que hayan sido silenciados explícitamente.

La contraparte del anterior. A veces ignorar un error es exactamente lo correcto, siempre que se diga cuál y por qué.

import os

try:
    os.remove("archivo_temporal.txt")
except FileNotFoundError:
    pass  # si ya no está, el objetivo se cumplió igual

La diferencia con el ejemplo anterior es el alcance: aquí se silencia un error concreto y previsto, no todos.

12. In the face of ambiguity, refuse the temptation to guess

Ante la ambigüedad, rechaza la tentación de adivinar.

Cuando hay varias interpretaciones posibles, conviene fijar la intención en lugar de dejar que el programa decida por su cuenta.

# Ambiguo: la codificación depende de la máquina donde se ejecute
with open("datos.txt") as archivo:
    contenido = archivo.read()

# Explícito: el resultado es el mismo en cualquier sistema
with open("datos.txt", encoding="utf-8") as archivo:
    contenido = archivo.read()

13. There should be one — and preferably only one — obvious way to do it

Debería existir una, y preferiblemente solo una, manera obvia de hacerlo.

Python intenta ofrecer una forma natural de resolver cada tarea habitual, en lugar de media docena de alternativas equivalentes.

for elemento in elementos:
    print(elemento)

Cualquiera que conozca el lenguaje reconoce esta construcción de inmediato, y esa previsibilidad es justamente la ventaja.

14. Although that way may not be obvious at first unless you’re Dutch

Aunque esa manera quizá no sea obvia al principio, a menos que seas holandés.

La broma alude a Guido van Rossum, creador de Python y neerlandés. Debajo del chiste hay una observación cierta: una solución parece «obvia» solo después de conocer las convenciones del lenguaje.

15. Now is better than never

Ahora es mejor que nunca.

Esperar indefinidamente a la solución perfecta tiene un costo. Una implementación razonable que existe suele valer más que una ideal que nunca se termina.

16. Although never is often better than right now

Aunque muchas veces «nunca» es mejor que «ahora mismo».

El contrapeso irónico del anterior. No todo tiene que resolverse de inmediato: una decisión precipitada puede costar más que la demora que evitó.

17. If the implementation is hard to explain, it’s a bad idea

Si la implementación es difícil de explicar, es una mala idea.

Si hace falta un discurso largo para justificar por qué algo funciona, suele haber complejidad accidental de por medio: la que agregó el diseño, no la que traía el problema.

18. If the implementation is easy to explain, it may be a good idea

Si la implementación es fácil de explicar, puede ser una buena idea.

Conviene reparar en el puede. Que algo se explique fácil no garantiza que sea correcto ni suficiente; la simplicidad es una buena señal, no una prueba.

19. Namespaces are one honking great idea — let’s do more of those!

Los espacios de nombres son una idea extraordinariamente buena; ¡hagamos más de ellos!

Un espacio de nombres agrupa nombres y los mantiene separados de los demás, de modo que dos cosas puedan llamarse igual sin estorbarse.

import math

print(math.pi)
print(math.sqrt(25))

Aquí pi y sqrt viven dentro de math, así que no chocan con variables o funciones propias que se llamen igual. En un programa grande, esa separación es lo que mantiene el código navegable:

import json
from datetime import datetime

datos = json.loads('{"usuario": "ana"}')
ahora = datetime.now()

La idea central

Si hubiera que comprimir los 19 aforismos en una lista corta, quedaría algo así:

  1. Código legible.
  2. Código explícito.
  3. Código sencillo.
  4. Código mantenible.
  5. Código fácil de explicar.

El Zen no pide escribir menos código, sino escribir código que otras personas puedan entender y mantener. Por eso insiste tanto en la claridad y la legibilidad: son las cualidades que sobreviven al paso del tiempo y al cambio de equipo.

Conclusión

El Zen de Python funciona como una brújula, no como un reglamento. Casi ninguna decisión de diseño tiene una única respuesta correcta, pero estos principios ayudan a distinguir cuándo una solución está añadiendo complejidad innecesaria y cuándo está haciendo el programa más claro.

Al final todo se reduce a una idea: escribe código que sea fácil de leer, entender, explicar y mantener. Y si quieres leerlo en su versión original, ya sabes dónde está:

import this

Referencia: PEP 20 — The Zen of Python.