Una colección de las buenas prácticas en python para programar de una forma más estandarizada o más idiomática, especialmente si somos nuevos en python.
- Documentación y comentarios adecuados
- Introducir excepciones
- Convención de nombres
- Operadores de comparación
- Argumentos predeterminados mutables
- Formato tipo string
- Entorno de script de nivel superior
- Expresiones condicionales
- Iterando sobre iteradores
- Indexación y conteo durante la iteración
- Uso de administradores de contexto
- Usar set para buscar en lugar de list
- Usando * al importar un módulo
- usando items() para iterar un diccionario
Documentación y comentarios adecuados
Es el primer y más importante punto al que debemos poner atención tener buenas prácticas en python. Cualquier código que escribamos debe estar bien documentado y comentado. Pero, ¿Por qué necesitamos la documentación del código? Un proyecto de una empresa puede durar años y estar desarrollado por varias personas. Los nuevos desarrolladores se unen al proyecto en cualquier momento, por lo que necesitarán saber y comprender el código. Simplemente pueden consultarlo y obtendrán una comprensión clara del código. Pensemos siempre en el próximo desarrollador si no hay documentación donde solamente hay código, sería realmente difícil seguir el desarrollo. Comentar también tiene el mismo propósito, debemos agregar comentarios en el código donde sea necesario.
Hay tres tipos de comentarios:
Comentario de una sola línea: comienzan con el símbolo del hashtag (#) y termina hasta el final de la línea.
# Esto es un comentario # Imprime ¡Hola Mundo! print('¡Hola mundo!')
Comentario de varias líneas: es un texto de varias líneas delimitado por ("""
) en cada extremo del comentario. No debe haber espacios en blanco entre el delimitador ("""
).
""" Este es un comentario de varias líneas, abarcando tres líneas. Aquí termina. """ print('¡Hola mundo!')
Comentarios de Docstring: Es una característica incorporada de python. Se utiliza para asociar documentación que se ha escrito con módulos, funciones, clases y métodos. Se usa justo debajo de las funciones, módulos, clases para decir lo que están haciendo. El comentario de la cadena de documentación está disponible mediante el atributo _doc_.
def add(a, b): """ Define sobre qué trata la función La suma de dos números a y b. """ return a + b print(add.__doc__) # Imprime el comentario que hay dentro de la función
Introducir excepciones
Python utiliza un objeto especial llamado exception
para controlar cualquier error que pueda ocurrir durante la ejecución de un programa.
Cuando ocurre un error durante la ejecución de un programa, Python crea una excepción. Si no se controla esta excepción la ejecución del programa se detiene y se muestra el error.
Para evitar la interrución de la ejecución del programa cuando se produce un error, es posible controlar la exepción que se genera con la instrucción try – except – else y hay buenas prácticas al respecto:
# mala practica try: hacer_algo() except: pass # Una forma ligeramente mejor (incluido el registro), pero sigue siendo una mala práctica: try: hacer_algo() except Exception: logging.exception() # aunque, logging es una buena práctica # Cuando no usamos 'Exception`, también estaremos capturando eventos como la salida del sistema. # Entonces, usar Exception significa que solo estamos capturando excepciones. # Una mejor forma: try: hacer_algo() except ValueError: # Aquí hemos utilizado un tipo específico de excepción, es decir, ValueError logging.exception() # algún código para manejar su excepción si es necesario
Convención de nombres
En python, se prefiere snake_case
para variables, funciones y nombres de métodos. Sin embargo, para las clases se utiliza PascalCase
.
# usar camelCase no es una convención en python para funciones def isEmpty(sampleArr): ... # en lugar de eso usa snake_case def is_empty(sample_arr): ...
Operadores de comparación
Hay varias formas de comparar en Python:
# No hacer esto: if 0 < x and x < 10: print('x es mayor que 0 pero menor que 10') # Lo siguiente es buena práctica: if 0 < x < 10: print('x es mayor que 0 pero menor que 10')
Argumentos predeterminados mutables
Consideremos el siguiente ejemplo de código:
def add_fruit(fruit, box=[]): box.append(fruit) return box red_box = add_fruit("apple") print(f"red box: {red_box}") yellow_box = add_fruit("mango") print(f"yellow box: {yellow_box}")
Entendamos paso a paso lo que está sucediendo:
- Estamos creando una función para agregar frutas (
str
) en una cajabox(list)
- Hay una función
add_fruit
que es responsable de agregar la fruta - Esta función toma 2 argumentos: fruta y caja.
- ¡Atención! : El segundo argumento aquí es un argumento predeterminado mutable.
Entonces, ¿qué es el argumento predeterminado mutable?
Un argumento en una función con valor predeterminado como mutable. En resumen, Python tiene tipos mutables e inmutables. La diferencia es:
- los mutables se pueden modificar
- los inmutables no se pueden modificar.
Lo que pasa en el código anterior es que se crea una nueva lista una vez que se define la función y se utiliza la misma lista en cada llamada sucesiva. Por lo que se usa un misma caja para cualqier fruta. Una buena práctica sería:
def add_fruit(fruit, box=None): if box is None: box = [] box.append(fruit) return box red_box = add_fruit("apple") print(f"red box: {red_box}") yellow_box = add_fruit("mango") print(f"yellow box: {yellow_box}")
Formato tipo string
La f en f-strings también puede significar «rápido». f-strings es más rápido que %-formatting y str.format(). Por ejemplo:
# Evita usar # %-formatting name = "James Bond" profession = "Secret Agent" print("Hello, %s. You are a %s." % (name, profession)) # Bueno, pero no mejor # str.format() print("Hello, {}. You are a {}.".format(name, profession)) # Corto y mucho mejor que las anteriores! # f-strings print(f"Hello, {name}. You are a {profession}.")
Entorno de script de nivel superior
Se ejecuta solo si se ejecuta como un script y no como un módulo, Hola mundo!
no se imprimirá si el módulo se importa a cualquier otro módulo.
# Filename: run.py if __name__ == '__main__': print('Hola mundo!') # $ python run.py # $ Hola mundo!
Expresiones condicionales
Una expresión condicional en Python es una expresión (en otras palabras, un fragmento de código que se evalúa como un resultado) cuyo valor depende de una condición. Pero la lectura debe ser intuitiva.
# Mala práctica if x < 10: return 1 else: return 2 # Buena práctica return 1 if x < 10 else 2
Iterando sobre iteradores
No se necesita iterar sobre los índices de los elementos en un iterador si no es necesario. Podemos iterar directamente sobre los elementos.
list_of_fruits = ["apple", "pear", "orange"] # mala práctica for i in range(len(list_of_fruits)): fruit = list_of_fruits[i] process_fruit(fruit) # buena práctica for fruit in list_of_fruits: process_fruit(fruit)
Indexación y conteo durante la iteración
Si vemos código de python desde un programador de C o Java, es posible que los bucles for
de Python le confundan. Python en realidad no tiene bucles for
, al menos no el mismo tipo de bucle for que tienen los lenguajes basados en C. Los bucles for
de Python son en realidad bucles foreach
.
# No usar: index = 0 for value in collection: print(index, value) index += 1 # Tampoco usar: for index in range(len(collection)): value = collection[index] print(index, value) # Definitivamente no usar esto: index = 0 while index < len(collection): value = collection[index] print(index, value) index += 1 # En este caso, usar `enumerate()` for index, value in enumerate(collection): print(index, value)
Uso de administradores de contexto
Python proporciona administradores de contexto que administran los gastos generales de inicialización y limpieza de los recursos y nos permiten enfocarnos en la implementación. Por ejemplo, en el caso de leer un archivo, no es necesario preocuparse
por cerrar el archivo manualmente.
d = {"foo": 1} # mala práctica f = open("./data.csv", "wb") f.write("some data") v = d["bar"] # KeyError # f.close() nunca se ejecuta, lo que conduce a problemas de memoria f.close() # buena práctica with open("./data.csv", "wb") as f: f.write("some data") v = d["bar"] # python aún ejecuta f.close() incluso si ocurre la excepción KeyError
Usar set para buscar en lugar de list
Los conjuntos se implementan usando hash en python, lo que hace que la búsqueda de elementos sea más rápida (O (1)) en comparación con la búsqueda en un lista(O(n)).
s = set(['s', 'p', 'a', 'm']) l = ['s', 'p', 'a', 'm'] # Esta bien para un número pequeño de elementos def lookup_list(l): return 's' in l # O(n) # Mejor para un número muy grande de elementos def lookup_set(s): return 's' in s # O(1)
Usando * al importar un módulo
Las importaciones siempre deben ser específicas. Import *
desde un módulo es una práctica muy mala que contamina el espacio de nombres de funciones clases, etc.
# mala práctica from math import * x = ceil(x) # buena práctica from math import ceil x = ceil(x) # we know where ceil comes from
usando items() para iterar un diccionario
d = { "name": "Aarya", "age": 13 } # No hacer esto for key in d: print(f"{key} = {d[key]}") # mejor hacer esto for key,val in d.items(): print(f"{key} = {val}")
Si hay un gran número de buenas prácticas en python, Google pone a disposición una guía de estilo de buenas prácticas aquí.