Recientemente publicamos una
traducción del material, que proporcionó consejos útiles para los programadores de Python. Ese material tiene una secuela que llamamos su atención hoy.

Nomenclatura de corte utilizando la función de corte
Trabajar con los muchos valores especificados por los índices puede convertirse rápidamente en un desastre, tanto en términos de soporte como en términos de legibilidad de código. Una forma de mejorar la situación es usar constantes para los valores especificados por los índices. Pero hay una mejor manera de escribir código de calidad:
En este ejemplo, puede ver que al dar los nombres de las
slice
usando la función de
slice
, y usando estos nombres para obtener los fragmentos de la cadena, pudimos deshacernos de los intrincados índices. Puede obtener más información sobre el objeto de
.start
utilizando sus
.start
,
.stop
y
.step
.
Solicitar una contraseña del usuario durante la ejecución del programa
Muchas herramientas de línea de comandos o scripts requieren un nombre de usuario y contraseña para funcionar. Si tiene que escribir dicho programa, puede encontrar
getpass
módulo
getpass
:
import getpass user = getpass.getuser() password = getpass.getpass()
Este paquete muy simple le permite solicitar la contraseña de un usuario, así como obtener un nombre de usuario recuperando el nombre con el que inició sesión. Sin embargo, cuando trabaje con contraseñas, debe tener en cuenta que no todos los sistemas admiten la ocultación de contraseñas. Python intentará notificarte. Si esto sucede, verá una advertencia correspondiente en la línea de comando.
Encontrar coincidencias cercanas en cadenas
Ahora hablemos de una característica un poco más misteriosa de la biblioteca estándar de Python. Suponga que se encuentra en una situación en la que necesita, utilizando un concepto como
la distancia de Levenshtein , para encontrar palabras en la lista que se parezcan a una determinada línea de entrada. Este problema se puede resolver utilizando el módulo
difflib
.
import difflib difflib.get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'], n=2)
El método
difflib.get_close_matches
las mejores coincidencias "suficientemente buenas". El primer argumento de este método especifica la cadena de búsqueda, el segundo argumento especifica la lista en la que se realiza la búsqueda. Este método puede pasar un argumento opcional
n
, que especifica el número máximo de coincidencias devueltas. Este método también admite el
cutoff
argumento con nombre opcional (de forma predeterminada se establece en
0.6
), que le permite establecer un valor umbral para evaluar coincidencias.
Trabajar con direcciones IP
Si tiene que escribir programas Python para trabajar con la red, esto significa que el módulo
ipaddress
puede serle muy útil. Una opción para usarlo es generar una lista de direcciones IP a partir de un rango de direcciones especificadas en el formato CIDR (enrutamiento entre dominios sin clase, direccionamiento sin clase).
import ipaddress net = ipaddress.ip_network('74.125.227.0/29')
Otra característica útil de este módulo es verificar que la dirección IP pertenezca a una determinada red:
ip = ipaddress.ip_address("74.125.227.3") ip in net
El módulo
ipaddress
tiene muchas otras características interesantes de las que no estoy hablando aquí. Lea más sobre él
aquí . Es cierto que al usar este módulo, considere las limitaciones con respecto a su trabajo conjunto con otros módulos relacionados con la programación de red. Por ejemplo, no puede usar instancias de
IPv4Network
como cadenas de direcciones. Los objetos similares para esto primero deben convertirse en cadenas usando
str
.
Depuración de un programa en la línea de comando
Si usted es uno de los que no quiere usar el IDE y escribe código en Vim o Emacs, entonces puede encontrarse en una situación en la que necesitaría un depurador como los del IDE. ¿Y sabes que? Ya tienes ese depurador. Para usarlo, simplemente ejecute el programa usando una estructura como
python3.8 -i
. El indicador
-i
permite, al finalizar el programa, iniciar un shell interactivo. Utilizándolo, puede examinar variables y funciones de llamada. Esta es una característica interesante, pero ¿qué pasa con un depurador real (pdb)? Experimentemos con el siguiente programa simple, cuyo código está en el archivo
script.py
:
def func(): return 0 / 0 func()
Ejecútelo con el
python3.8 -i script.py
y obtenga lo siguiente:
Vemos el lugar del programa donde ocurrió el bloqueo. Establecer un punto de interrupción:
def func(): breakpoint()
Ejecute el script nuevamente.
script.py(3)func()
-> return 0 / 0
(Pdb) #
(Pdb) step
ZeroDivisionError: division by zero
> script.py(3)func()
-> return 0 / 0
(Pdb)
En la mayoría de las situaciones, el comando de
print
y los resultados de rastreo son suficientes para depurar los scripts, pero a veces para lidiar con una falla compleja, debe profundizar en el programa y comprender la esencia de lo que está sucediendo. En tales casos, los puntos de interrupción se establecen en el código y se examina el programa. Por ejemplo, observan los argumentos de las funciones, evalúan las expresiones, verifican los valores de las variables o, como se muestra arriba, simplemente ejecutan el código paso a paso. Pdb es un contenedor Python completamente funcional. En este shell, puedes hacer casi cualquier cosa. En el curso del trabajo, algunos comandos específicos del depurador serán útiles, para lo cual se puede encontrar ayuda
aquí .
Declarando múltiples constructores en una clase
La sobrecarga de funciones es una de las características que se utilizan ampliamente en varios lenguajes de programación, pero no en Python. Y aunque no puede sobrecargar una función regular en Python, podemos usar algo como sobrecargar los constructores usando métodos de clase:
import datetime class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def today(cls): t = datetime.datetime.now() return cls(t.year, t.month, t.day) d = Date.today() print(f"{d.day}/{d.month}/{d.year}")
En una situación similar, en lugar de usar métodos de clase, puede sentirse tentado a poner toda la lógica de los constructores alternativos en
__init__
y resolver el problema usando
*args
,
**kwargs
y muchas
if
. El resultado puede ser un código de trabajo, pero este código será difícil de leer y mantener. Aquí recomendaría poner un mínimo de lógica en
__init__
y realizar todas las operaciones en métodos / constructores separados. Con este enfoque, tendremos a nuestra disposición un código limpio que será conveniente tanto para el autor de este código como para quien lo use.
Resultados de llamadas de función de almacenamiento en caché utilizando un decorador
¿Alguna vez ha escrito funciones que realizan algunas operaciones largas de lectura / escritura, o más bien cálculos recursivos lentos? Al mismo tiempo, ¿creía que el almacenamiento en caché de los resultados no dañaría tales funciones? Puede almacenar en caché (memorizar) los resultados de una llamada de función utilizando el decorador
functools
módulo
functools
:
from functools import lru_cache import requests @lru_cache(maxsize=32) def get_with_cache(url): try: r = requests.get(url) return r.text except: return "Not Found" for url in ["https://google.com/", "https://martinheinz.dev/", "https://reddit.com/", "https://google.com/", "https://dev.to/martinheinz", "https://google.com/"]: get_with_cache(url) print(get_with_cache.cache_info())
En este ejemplo, ejecutamos solicitudes GET cuyos resultados se almacenan en caché (se pueden almacenar en caché hasta 32 resultados). Aquí puede ver que obtenemos información sobre la función de caché utilizando el método
cache_info
. El decorador también nos proporciona el método
clear_cache
, que se usa para
clear_cache
caché. Aquí también me gustaría señalar que el almacenamiento en caché no se puede usar con funciones que tienen efectos secundarios, o con funciones que crean objetos mutables con cada llamada.
Encontrar elementos que se encuentran en el objeto iterable con mayor frecuencia
Estar en la lista de dichos elementos que se encuentran en él con más frecuencia que otros es una tarea muy común. Puede resolverlo, por ejemplo, utilizando el bucle
for
y un diccionario, que recopilará información sobre la cantidad de elementos idénticos. Pero este enfoque es una pérdida de tiempo. El hecho es que puede resolver estos problemas utilizando la clase
Counter
del módulo de
collections
:
from collections import Counter cheese = ["gouda", "brie", "feta", "cream cheese", "feta", "cheddar", "parmesan", "parmesan", "cheddar", "mozzarella", "cheddar", "gouda", "parmesan", "camembert", "emmental", "camembert", "parmesan"] cheese_count = Counter(cheese) print(cheese_count.most_common(3))
Los mecanismos internos de la clase
Counter
se basan en un diccionario que almacena la correspondencia de elementos y el número de entradas en la lista. Por lo tanto, el objeto correspondiente se puede usar como un objeto
dict
regular:
print(cheese_count["mozzarella"])
Además, cuando trabajamos con
Counter
, tenemos a nuestra disposición el método de
update(more_words)
, que se utiliza para agregar nuevos elementos al contador. Otra característica útil de
Counter
es que le permite usar operaciones matemáticas (suma y resta) cuando trabaja con instancias de esta clase.
Resumen
Creo que la mayoría de los consejos dados hoy pueden ser utilizados por quienes escriben en Python casi a diario. Espero que encuentres entre ellos algo que te sea útil.
Estimados lectores! ¿Conoces algún truco interesante de programación de Python? Si es así, por favor compártalos.
