El formato del código en Python es un componente clave del lenguaje. Este es el que indica al intérprete, mediante la indentación, cuáles son las partes que pertenecen a un bucle, una función, una clase o un método. Aun así, el lenguaje es flexible y permite cierta libertad a la hora de escribir. Por eso, es posible encontrarse con código descuidado que es feo y difícil de leer debido a la existencia o falta de espacios y saltos de línea. Una manera de solucionar esto es usar un formateador de código, con el que podemos estar seguro de que todo lo que se escriba siga los estándares, sea homogéneo y, de esta forma, su lectura y revisión sea más sencilla. Uno de los más populares es YAPF. Veamos cómo se puede formatear automáticamente código Python con YAPF.
Instalación de YAPF
YAPF es un paquete de Python que se puede instalar como es habitual mediante el uso del comando pip
. Para instalarlo en un ordenador con Python solamente hay que abrir la terminal y escribir el comando
pip install yapf
Una vez hecho esto debería estar disponible el comando yapf
con el que se puede formatear el código Python de una forma automática.
Código de ejemplo
Veamos por ejemplo el siguiente código.
def suma(a , b = 0 ) : return a+ b def resta (a, b = 0): return a -b class Contador: def __init__(self, counter =0 ): self.counter = counter def suma(self,valor = 0): self.counter += valor contador = Contador() contador.suma( 5) data = { 'a':1, 'b': 2,'c': 3, 'd':4} resultado = suma(data['a'], data ['b' ])
¿Es feo? ¿Es difícil de leer? Yo creo que sí. El código no es complejo, pero sí este estuviese bien formateado su lectura sería más sencilla. Facilitando la revisión de este. En el ejemplo se definen dos funciones ( suma()
y resta()
) que no están separadas por un salto de línea, algo que dificulta ver dónde termina una y comienza la siguiente. Además, existen espacios que complican la visualización de los parámetros y las operaciones.
Por otro lado, en el código también se define una clase ( Contador
), pero sus métodos están separados por un salto de línea. Tampoco hay dos saltos de línea al terminar la definición de la clase. Lo que hace más complejo de lo necesario la lectura de esta.
Finalmente se usa el código, pero a la hora de definir un diccionario los espacios adicionales obliga a realizar un esfuerzo para ver cuántos elementos continentemente. Lo mismo al usar la función suma()
.
Si este ejemplo se ha guardado en el archivo complejo.py
y se ejecuta el comando
yapf complejo.py > formato.py
Se obtiene un nuevo archivo formato.py
como resultado con el siguiente código.
def suma(a, b=0): return a + b def resta(a, b=0): return a - b class Contador: def __init__(self, counter=0): self.counter = counter def suma(self, valor=0): self.counter += valor contador = Contador() contador.suma(5) data = {'a': 1, 'b': 2, 'c': 3, 'd': 4} resultado = suma(data['a'], data['b'])
Mucho mejor, ¿no? Ahora hay dos líneas después de la definición de una función o clase, una línea entre los métodos de la clase, no hay espacios innecesarios y el diccionario se ha simplificado en una línea.
Formatear en el propio archivo y carpetas
En el ejemplo anterior se ha creado un nuevo archivo con el código formateado, pero un proyecto normar esto no es práctico. Por eso se puede usar la opción --in-place
para indicarle a YAPF que modifique los archivos originales. Pudiéndose usar además comodines para indicar al formateado que modifique todos los archivos Python de una carpeta. Así el siguiente comando formateara todos los archivos Python que existan en la carpeta actual
yapf --in-place *.py
Por otro lado, si se desea modificar todos los archivos de un proyecto, lo que incluye subcarpetas, se puede usar el comando
yapf --in-place **/*.py
Si se desea ignorar algunas carpetas en un proyecto esto se puede indicar mediante creando un archivo .yapfignore
dónde se debe escribir el nombre de estas.
Opciones de formato
YAPF puede dar formato al código en base a varios estándares, por defecto usa PEP8, pero también puede usar el formato de Google si lo preferimos. Lo que se puede indicar mediante el modificador --style
o a través de un archivo de configuración. Por ejemplo, para ver formatear el código anterior empleando el estilo de Google solamente se tendría que ejecutar el siguiente comando.
yapf complejo.py --style='{based_on_style:google}' > google.py
Lo que crea el siguiente archivo google.py
.
def suma(a, b=0): return a + b def resta(a, b=0): return a - b class Contador: def __init__(self, counter=0): self.counter = counter def suma(self, valor=0): self.counter += valor contador = Contador() contador.suma(5) data = {'a': 1, 'b': 2, 'c': 3, 'd': 4} resultado = suma(data['a'], data['b'])
En este ejemplo tan sencillo las diferencias entre uno y otro son sutiles, pero en programas más complejos existirían más diferencias. Siendo lo más claro el salto la línea en blanco que existe antes del primer método de la clase. Se puede consultar todas las opciones que tiene YAPF en la documentación del proyecto para adaptar el resultado a nuestras preferencias.
Conclusiones
En esta entrada se ha visto cómo gracias a YAPF se puede formatear automáticamente código Python de una manera fácil y sencilla. Un programa con el que podemos estar seguros de que nuestro código cumple con diferentes estándares de formato (PEP8, Google o Facebook) o uno propio.
Creo que herramientas cómo estas deben ser parte del flujo de trabajo a la hora de trabajar con código. Un código más limpio y formateado es más fácil de leer y, por lo tanto, hace nuestro trabajo diario, y el de nuestros compañeros, más sencillo. Aumentado la productividad del equipo. Algo que, si tenemos en cuenta la teoría de las ventanas rotos, hace que los miembros del equipo sean inconscientemente más cuidadosos para mantener la calidad del código. Lo que se traduce en menos errores y problemas.
Imagen de PublicDomainPictures en Pixabay