Curso

¿Qué es el Zen de Python?
El Zen de Python es un conjunto de diecinueve aforismos que sirven como principios rectores del diseño de Python. En realidad, iban a ser veinte; pero Guido van Rossum, creador de Python, aún no ha añadido el aforismo final tal y como lo concibió Tim Peters, autor del Zen de Python. Según se cuenta, Guido dijo que el vigésimo aforismo que falta es “una broma interna rara de Tim Peters”.
A pesar de ese aforismo ausente, el Zen de Python se estandarizó como PEP 20 en 2004 por su enorme influencia en la forma de trabajar de los programadores de Python. Seguir el Zen de Python no es obligatorio, pero conocerlo y tenerlo presente es muy recomendable. Si alguna vez olvidas las lecciones, puedes refrescar la memoria fácilmente ejecutando import this en el intérprete de Python.
>>> import this
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!
En este artículo, vamos a recorrer cada lección con más detalle.
#1 Lo bello es mejor que lo feo
Si programas, no hay duda de que tienes un alto nivel. Resolver problemas con código no es tarea fácil, pero como pythonista se espera más de ti. Un código bonito es mejor que un código feo. El ascenso meteórico de Python se debe en parte a su accesibilidad: es simple, legible y elegante. Como desarrollador de Python, tienes la responsabilidad de mantener el estándar “pythónico” escribiendo código bonito.
¿Qué es un código bonito? Es subjetivo: la belleza está en el ojo de quien mira y todo eso. Una regla práctica para mantener el rumbo es escribir un código limpio y legible, que otras personas desarrolladoras puedan entender con facilidad. Por ejemplo:
"""
Initial code was created by Vishal Sharma
See: https://towardsdatascience.com/the-zen-of-python-a-guide-to-pythons-design-principles-93f3f76d088a
"""
def collatz(num):
if num % 2 == 0:
return num // 2
else:
return 3 * num + 1
number = input("Enter a number: ")
while number != 1:
number = collatz(int(number))
print(number)
"""
Enter a number: 5
16
8
4
2
1
"""
El código anterior funciona perfectamente, pero no necesariamente es bonito. Tenemos un else innecesario en la función collatz que podemos eliminar así:
def collatz(num):
if num % 2 == 0:
return num // 2
return 3 * num + 1
Así, cuando tengas dos fragmentos de código que funcionan, deberías optar por el que sea más simple, legible y fácil de entender.
#2 Lo explícito es mejor que lo implícito
Decir que un aforismo “se explica solo” es un gran error; aun así verás a gente haciéndolo. La idea detrás de “lo explícito es mejor que lo implícito” es que un código más claro y detallado es preferible a uno indirecto. Haz todo lo posible para que la funcionalidad de tu código no quede oculta tras construcciones rebuscadas. Alguien sin conocimiento previo de tu programa debería poder entender qué está pasando en tu código.
#3 Lo simple es mejor que lo complejo
Probablemente te reirías si tu colega sacase una hidrolimpiadora para fregar los platos después de cenar. Además de ser una ocurrencia absurda, es muy probable que acaben rotos. Del mismo modo, aplicar una solución muy compleja a un problema sencillo de programación es poco práctico. No hace falta enredar tu solución, aunque creas que te hace parecer más listo. Puedes causar más daños que beneficios, y en Python no se valora.
Mira esta función para invertir una cadena:
def reverse_string(string):
if len(string) == 1:
return string
else:
return reverse_string(string[1:]) + string[0]
string = "kurtis"
print(reverse_string(string))
"""
sitruk
"""
Este código resuelve el problema, pero es innecesariamente complejo. Si dominas Python, sabes que una cadena se puede invertir con indexación.
string = "kurtis"
# solución con función anónima
reverse_string = lambda x: x[::-1]
# solución con función
def reverse(string):
return string[::-1]
print(reverse_string(string))
print(reverse(string))
"""
sitruk
sitruk
"""
#4 Lo complejo es mejor que lo complicado
Lavar platos con una hidrolimpiadora es poco práctico: mejor algo simple como el grifo. Pero ¿y si el problema fuera limpiar un 4x4 Range Rover? El aforismo anterior y este nos recuerdan que un mismo problema puede requerir técnicas simples o complejas. Limpiar un 4x4 no es un problema sencillo, y aplicar lo mismo que para los platos puede funcionar, pero sería más engorroso que usar una hidrolimpiadora. Favorece la simplicidad frente a la complejidad, pero cuando la simplicidad sea poco práctica, mejor elige complejidad: conoce los límites de lo simple.
#5 Lo plano es mejor que lo anidado
A los programadores nos encanta organizar cosas en categorías, subcategorías y sub-subcategorías para separar funcionalidades. Aunque suene ordenado, estructurar el código así puede generar más confusión que orden.
No pasa nada por concentrar todo tu código en un módulo de primer nivel: así no tendrás que hacer algo como from spam.foo.bar.john.doe import chicken para acceder a una funcionalidad concreta. Cuantas más subcategorías añadas, más se complica tu código. Procura mantener una estructura plana siempre que sea posible.
#6 Lo disperso es mejor que lo denso
Se considera que los programadores están entre las personas más inteligentes, así que no hace falta subrayarlo con trucos enrevesados. El clásico es “cómo hacer [tarea complicada] en 1 línea de código”. A veces un one-liner está justificado, pero evita sacrificar legibilidad solo por concentrarlo todo en una línea.
Por ejemplo:
"""
Code source Al Sweigart
See: https://inventwithpython.com/blog/author/al-sweigart.html0
"""
print('\n'.join("%i bytes = %i bits which has %i possible values." % (j, j*8, 256**j-1) for j in (1 << i for i in range(8))))
"""
1 bytes = 8 bits which has 255 possible values.
2 bytes = 16 bits which has 65535 possible values.
4 bytes = 32 bits which has 4294967295 possible values.
8 bytes = 64 bits which has 18446744073709551615 possible values.
16 bytes = 128 bits which has 340282366920938463463374607431768211455 possible values.
32 bytes = 256 bits which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values.
64 bytes = 512 bits which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values.
128 bytes = 1024 bits which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values.
"""
Ese código funciona, pero es una pesadilla de leer: está apelotonado y cuesta seguirlo.
Veamos cómo queda el mismo código si lo escribimos de forma más aireada:
# Ejemplo disperso
bytes_and_bits = {j: j*8 for j in (1 << i for i in range(8))}
for bytes, bits in bytes_and_bits.items():
print(f"{bytes} bytes = {bits} which has {256**bytes-1} possible values")
"""
1 bytes = 8 which has 255 possible values
2 bytes = 16 which has 65535 possible values
4 bytes = 32 which has 4294967295 possible values
8 bytes = 64 which has 18446744073709551615 possible values
16 bytes = 128 which has 340282366920938463463374607431768211455 possible values
32 bytes = 256 which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values
64 bytes = 512 which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values
128 bytes = 1024 which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values
"""
Este código es mucho más fácil de leer y hace exactamente lo mismo que el one-liner.
#7 La legibilidad importa
Si no lo habías deducido ya, en Python la legibilidad cuenta. Tu trabajo es escribir el código una vez. Sin embargo, es muy probable que se lea muchas veces. Teniéndolo en cuenta, quitar vocales a nombres de variables y funciones no es buena idea: si puedes llamar a una función create_lst o create_list, elige la segunda.
#8 Los casos especiales no son tan especiales como para romper las reglas
Python (y la programación en general) está lleno de buenas prácticas que conviene seguir. Es mejor ajustarse a ellas que hacerlo “a tu manera”, porque eso suele llevar a un código inconsistente y poco legible.
#9 Aunque la practicidad supera a la pureza
La lección nueve amplía la ocho. Sí, es mejor seguir las buenas prácticas, pero forzarte a cumplirlas a rajatabla también puede terminar en un código difícil de leer. Por tanto, cada regla puede tener su excepción. Si tu forma de resolver un problema es más práctica, legible y fácil de entender, es mejor apartarse de la ortodoxia.
#10 Los errores nunca deberían pasar en silencio
Un error silencioso es cuando un programa devuelve un código de error o None en lugar de lanzar una excepción. Es mejor que un programa se caiga a que oculte el error y siga ejecutándose. A la larga, silenciar errores puede introducir fallos mucho más difíciles de detectar y corregir.
#11 A menos que los silencies explícitamente
La lección once amplía la diez. Hay situaciones en las que puede interesarte ignorar ciertos errores de tu programa. En esos casos, la buena práctica es silenciarlos de forma explícita en el código.
#12 Ante la ambigüedad, resiste la tentación de adivinar
Los ordenadores solo hacen lo que les decimos: si tu código no se comporta como quieres, es porque hace exactamente lo que le has indicado. Intentar arreglarlo probando a ciegas soluciones hasta que funcione es mala estrategia: puedes estar tapando el problema en lugar de resolverlo. Resiste la tentación. Mejor razona la lógica del problema y aplica pensamiento crítico para dar con la solución adecuada.
#13 Debería haber una —y preferiblemente solo una— forma obvia de hacerlo
El lema de Perl es: “¡Hay más de una forma de hacerlo!”. Tener demasiadas opciones suele llevar a la parálisis por elección. Algo similar ocurre cuando hay varias maneras de escribir código para lograr lo mismo. Tienes más flexibilidad al escribir, pero ahora para leerlo debes conocer todas las formas posibles en que podría haberse escrito: ese esfuerzo extra es innecesario.
#14 Aunque esa forma puede no ser obvia al principio, a menos que seas neerlandés
Este aforismo muestra el sentido del humor de Tim Peters: Guido van Rossum, creador del lenguaje Python y Benevolent Dictator For Life (BDFL), es neerlandés. Es una broma para recordarnos que entender y recordar las reglas de Python es difícil para todos excepto para su creador.
#15 Ahora es mejor que nunca
Este aforismo nos dice que un código que entra en un bucle infinito o se queda colgado es peor que un código que no lo hace.
#16 Aunque a menudo nunca es mejor que “justo” ahora
En la línea de la lección anterior: es mejor esperar a que tu programa termine de ejecutarse que pararlo antes de tiempo y obtener resultados incorrectos.
#17 Si la implementación es difícil de explicar, es mala idea
No basta con que tú entiendas tus implementaciones: “yo sé lo que quiero decir” no sirve. Programar es un trabajo en equipo y, si no puedes explicar tu implementación a tus compañeros, es muy probable que hayas complicado en exceso la solución.
#18 Si la implementación es fácil de explicar, puede ser buena idea
Ahora bien, que sea fácil de explicar no garantiza que sea buen código; solo que es fácil de entender. Puede seguir habiendo problemas, pero el hecho de que se explique bien indica que vas por buen camino.
#19 Los espacios de nombres son una idea fantástica: ¡hagamos más de eso!
Un espacio de nombres es una abstracción en Python para organizar los nombres asignados a objetos en un programa. Con un determinado espacio de nombres y un alcance, Python sabe a qué objeto te refieres cuando llamas a un nombre simbólico. Este aforismo viene a decir que la forma en que Python organiza los nombres simbólicos por debajo es, sencillamente, estupenda.
Conclusión
En este artículo, hemos compartido nuestra interpretación del Zen de Python, unas pautas pensadas para animar a quienes programan en Python a escribir código limpio y legible. Mientras que algunos ven el Zen de Python como la guía definitiva para escribir código sin fricciones, otros se lo toman con más calma. Te sugerimos aplicar estos principios a tu propio código para comprobar de primera mano cómo mejoran tu trabajo. Si quieres aprender más sobre cómo escribir código optimizado, echa un vistazo al curso de DataCamp Writing Efficient Python Code.
