PEP 20 – El Zen de Python

zen de python

Al igual que cada arquitecto/a impregna sus creaciones con su propia visión y personalidad, o la cocina de cada chef suele tener una esencia única, cada desarrollador/a escribe código según sus gustos, por lo que el código de diferentes desarrolladores/as suele ser muy heterogéneo (diferente).

Pero y ¿si se tuvieran unas directrices a seguir, que ayudaran a discernir de qué forma hay que escribir en cada lenguaje? ¿no sería mucho más simple tener una forma, y solo una forma, de escribir código? con esta motivación se definió la PEP 20 o el Zen de Python.

Reglas del Zen de Python

El Zen de python consta de 19 reglas que de aplicarse correctamente en cualquier código para convertirlo en código Pythónico. Se pueden obtener ver en la definición de la PEP 20 https://www.python.org/dev/peps/pep-0020/ o ejecutando el siguiente código en cualquier intérprete:

>>> 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!
"""

Bonito es mejor que feo

Beautiful is better than ugly

Los adjetivos de bonito o feo suelen ser muy subjetivos aunque cuando se refiere a código, cualquiera con algunas decenas de miles de líneas escritas puede apreciar si un código es bonito o feo, aplicando las siguientes reglas o con reglas propias que da la experiencia.

# ejemplo de codigo feo
gatos=4;perros=6;patas=34;assert patas==(gatos*perros*4),'Número de patas dispar';

# ejemplo de codigo bonito
gatos = 4
perros = 6
patas = 34
assert patas == (gatos * 4) + (perros * 4), 'Número de patas dispar'

Explícito es mejor que implícito

Explicit is better than implicit

Cuando un código es explícito, no requiere que el lector tenga que intuir o saber de antemano algún elemento implícito del sistema, haciendo que la legibilidad mejore considerablemente.

A veces convertir un código implícito en explícito es tan simple como añadir algunas variables intermedias con nombres apropiados, o no concatenar funciones o simplemente no hacer uso de variables globales sino pasar las variables usando argumentos.

# version implicita
def metros_a_pulgadas_dobles(metros):
    return metros * 39.3701 * 2

# version explicita
def metros_a_pulgadas_dobles(metros):
    pulgadas_por_metro = 39.3701
    multi_doble = 2
    return metros * pulgada_por_metro * multi_doble

Simple es mejor que complejo

Simple is better than complex.

Un sistema complejo se define como un sistema compuesto de muchas partes independientes conectadas entre sí, pero que no tienen relaciones ocultas entre los componentes.

Si el sistema está correctamente implementado, cada parte independiente será simple si se estudia de forma aislada, por lo que, el estudio del sistema completo se podría simplificar en el estudio de cada parte simple.

Complejo es mejor que complicado

Complex is better than complicated.

Sin embargo, un sistema complicado, se compone de elementos simples que no son independientes entre sí, sino que el sistema conoce de alguna lógica extra que convierte el sistema en complicado.

# version compleja interconectada
LIMITE_SUPERIOR = 32
LIMITE_INFERIOR = 3
POSICION = 1
def evaluar_cambio(valor):
   prev_pos = POSICION
   if valor > (LIMITE_SUPERIOR + LIMITE_INFERIOR * 5 / 4):
        nueva_pos = 1
   elif valor < (LIMITE_INFERIOR + LIMITE_INFERIOR * 2 / 4):
        nueva_pos = 0
   return prev_pos != nueva_pos

# version simple
def evaluar_cambio(valor, valor_actual):
    debe_cambiar = False
    if valor_actual == 1:
        debe_cambiar = debe_apagar(valor)
    elif valor_actual == 0:
        debe_cambiar = debe_encender(valor)
    return debe_cambiar

def debe_encender(valor, valor_superior=LIMITE_SUPERIOR, valor_inferior=LIMITE_INFERIOR):
    limite = valor_superior + valor_inferior * 5 / 4
    return valor > limite

def debe_apagar(valor, valor_superior=LIMITE_SUPERIOR, valor_inferior=LIMITE_INFERIOR):
    limite = valor_superior + valor_inferior * 2 / 4
    return valor < limite

Por tanto por orden de preferencia sería (> == mejor que):

Simple > Complejo > Complicado

Plano es mejor que anidado

Flat is better than nested.

La capacidad de retención y comprensión de cada desarrollador es limitada, por tanto si se anidan las sentencias en vez de mantenerlas lo más planas posibles, se suele mermar la capacidad cansando al lector del código.

Una forma de aplanar un código anidado es usando funciones planas y otra podría ser usando listas por comprensión, aunque la segunda opción suele quedar muy densa fácilmente.

# version anidada
valores_ajustados = []
for s in sistemas:
    sensores = sensores_sistema(s)
    for sensor in sensores:
        valores_s = valores_sensor(sensor)
        for val in valores_s:
            valores_ajustados.append(ajustar_valor(val))

# version aplanada pero densa
valores_ajustados = [ajustar_valor(val) for val in valores_sensor(sensor) for sensor in sensores_sistema(s) for s in sistemas]

# version en funciones simples, testeables y escalables
def valores_del_sistema_ajustados(sistemas):
    for sistema in sistemas:
        yield valores_sistema(sistema)

def valores_sistema(sistema):
    for sensores in sistema:
        yield valores_sensores(sensores)

def valores_sensores(sensores):
    for sensor in sensores:
        yield valores_sensor_ajustados(sensor)

def valores_sensor_ajustados(sensor):
    for valor in valores_sensor(sensor):
        yield ajustar_valor(valor)

Disperso es mejor que denso

Sparse is better than dense

Cuando se aumenta la densidad del código haciendo en pocas líneas muchas operaciones se puede hacer perder el foco del lector, por tanto es muy recomendable añadir espacios entre bloques lógicos.

# version densa
print(','.join(map(str, [x ** 2 for x in range(5)])))

# version dispersa
a = [x ** 2 for x in range(5)]
b = map(str, a)
c = ','.join(b)
print(c)

La legibilidad importa

Readability counts.

El código se escribe una vez pero se leen cientos de veces, por lo tanto es muy importante prestar especial atención a mejorar la legibilidad lo más posible, eligiendo los mejores nombres, separando funciones convenientemente o clases cuando son necesarios.

Existen muchas técnicas para mejorarlo e incluso libros sobre este tema como los principios SOLID o los libros de Clean Code que son totalmente recomendables.

# version mas legible
lista_de_cuadrados = [x ** 2 for x in range(5)]
cadenas_de_cuadrados = map(str, lista_de_cuadrados)
cuadrados_formateados = ','.join(cadenas_de_cuadrados)
print(cuadrados_formateados)

Los casos especiales no son lo suficientemente especiales para romper reglas

Special cases aren’t special enough to break the rules

Cuando se definen unas reglas hay que cumplirlas, de lo contrario no tienen razón de existir. Los casos «especiales» son la excusa que se pone para romper las reglas pero realmente son sinónimo de «conozco las reglas pero en vez de cambiar el código para cumplirarlas, prefiero romperlas», lo que debería de ser inadmisible dado que a la larga (conlleva al desastre).

Practicidad vence a la pureza

Although practicality beats purity

En multitud de ocasiones nos encontramos en la situación de querer escribir el código más puro, que sigue todos los patrones de diseño «a raja tabla» y que conlleva a que los sistemas sean demasiado genéricos o que se tarden una eternidad en desarrollar, es muy importante encontrar un equilibrio entre lo que es práctico (e importante) y la pureza.

Los errores nunca deberían de ocurrir silenciosamente

Errors should never pass silently.

Cuando se trabaja bajo presión y se encuentran errores se tienden a ocultar o a tomar medidas demasiado drásticas como la siguiente:

try:
    codigo_erroneo()
except Exception:
   pass

O lo que es lo mismo «se que este código falla de vez en cuando, cuando lo haga sigue sin más», esto no es solo un antipatrón sino que demuestra apatía y una desgana de hacer código profesionalmente. Si hay un error debe ser visible para poder ser arreglado.

A no ser que se silencien explícitamente

Unless explicitly silenced

Existen excepciones al caso anterior que se dan cuando se ha estudiado la situación, se conoce el error y explícitamente se silencia (o se actúa en consecuencia).

Si el error que se ha detectado es un ValueError (por ejemplo) pero se sabe que no es problemático, se debe de manejar adecuadamente, incluso pudiendo ser silenciado.

try:
    codigo_erroneo()
except ValueError:
   logger.debug('Value Error manejado correctamente')

En el caso de ambigüedad, rechaza la tentación de adivinar

In the face of ambiguity, refuse the temptation to guess

Este concepto aplica a muchos ámbitos del desarrollo, es mucho mejor tener claro qué se está construyendo y poder crear tests, que exactamente definan y comprueben el buen comportamiento del sistema, eliminando cualquier ambigüedad.

Debería de haber una – y preferiblemente sólo una – forma obvia de hacerlo

There should be one– and preferably only one –obvious way to do it

Si la forma de implementar el problema no parece obvia, quizás no sea la más correcta y haya que seguir pensando en otra opción.

Aunque la forma no parezca obvia a la primera, a no ser que seas Holandés

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

Es normal que no aparezca la forma obvia la primera vez que piensa la solución, por lo que puede requerir de un método iterativo.

El guiño que se añade en esta regla sobre los holandeses hace referencia la nacionalidad del Dictador Benevolente y creador de Python Guido van Rossum.

Ahora es mejor que nunca

Now is better than never

En el desarrollo de software siempre hay tareas que realizar y si no se priorizan las tareas importantes para hacerlas cuando salen los problemas, estos pueden alargarse en el tiempo hasta no hacerlas nunca.

Aunque nunca es a menudo mejor que ahora mismo

Although never is often better than right now

Quiere decir que no hay que forzar la realización de tareas tanto como para dejar lo que se está desarrollando actualmente, para desarrollar una tarea nueva, evitando así el cambio de contexto.

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

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

Esta regla suele aplicarse en muchos ámbitos en general, dado que si no eres capaz de explicar la idea de forma simple es que no la visualizas de forma simple por lo que quizás sea necesario consensuar la solución hasta tenerla clara.

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

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

Cuando se puede explicar la idea a cualquier otra persona (o patito de goma) suele ser síntoma de tener los conceptos claros y de ser una solución genial.

Los espacios de nombres son una buena idea, ¡usemos más de ellos!

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

Los espacios de nombres en Python se pueden crear de múltiples formas y ayudan mucho a desacoplar código y de hacerlo más modular, por lo que se recomienda usarlos más.

Importancia del Zen de Python

La importancia de la PEP 20 radica en intentar definir una guía de principios de cómo debe de crearse el código para considerarse Pythónico.

El Zen de Python podría exportarse a otros lenguajes dado que muchas de sus reglas no son únicas para Python sino aplicables a cualquier lenguaje.

Dado que Python es uno de los pocos lenguajes con unas directrices tan claras hace que el lenguaje sea aún más extraordinario.

Libros recomendados para aprender Python

Estos son los libros que pueden ayudarte a aprender Python, aprender a programar, tipos de datos, algoritmia y mucho más.

Disponible en:

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Ver más

  • Responsable: Oscar Ramirez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento: No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a ionos (1&1) que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Publicar un comentario