8 trucos de Python utilizados por programadores experimentados

imagen



Aquí hay ocho ingeniosos trucos de Python que estoy seguro de que aún no has visto. ¡Aplique estos trucos a su código de Python para hacerlo más conciso y eficaz!



1. Ordenar objetos por múltiples claves



Supongamos que queremos ordenar la siguiente lista de diccionarios:



people = [
{ 'name': 'John', "age": 64 },
{ 'name': 'Janet', "age": 34 },
{ 'name': 'Ed', "age": 24 },
{ 'name': 'Sara', "age": 64 },
{ 'name': 'John', "age": 32 },
{ 'name': 'Jane', "age": 34 },
{ 'name': 'John', "age": 99 },
]


Pero no solo queremos ordenarlos por nombre o edad, queremos ordenarlos por ambos campos. En SQL, será una consulta como esta:



SELECT * FROM people ORDER by name, age


En realidad, hay una solución muy simple para este problema, gracias a la garantía de Python de que las funciones de clasificación proporcionan persistencia de clasificación . Esto significa que los elementos que se comparan mantienen su orden original.



Para lograr la clasificación por nombre y edad, podemos hacer esto:



import operator
people.sort(key=operator.itemgetter('age'))
people.sort(key=operator.itemgetter('name'))


Observe cómo cambié el orden. Primero ordenamos por edad, y luego por nombre. Utilizando operator.itemgetter()obtenemos los campos de edad y nombre de cada diccionario en la lista.



Esto nos da el resultado que queríamos:



[
 {'name': 'Ed',   'age': 24},
 {'name': 'Jane', 'age': 34},
 {'name': 'Janet','age': 34},
 {'name': 'John', 'age': 32},
 {'name': 'John', 'age': 64},
 {'name': 'John', 'age': 99},
 {'name': 'Sara', 'age': 64}
]


Los nombres se ordenan primero, la edad se ordena si el nombre coincide. Por lo tanto, todos los Jones están agrupados por edad.



Fuente de inspiración: pregunta de StackOverflow .



2. Inclusiones de listas (generador de listas)



Las inclusiones de listas pueden reemplazar los bucles feos que se utilizan para completar la lista. Sintaxis básica para inclusiones de lista:



[ expression for item in list if conditional ]


Un ejemplo muy simple para llenar una lista con una secuencia de números:



mylist = [i for i in range(10)]
print(mylist)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


Y como puedes usar una expresión, también puedes hacer algunas matemáticas:



squares = [x**2 for x in range(10)]
print(squares)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


O incluso llamar a una función externa:



def some_function(a):
    return (a + 5) / 2
    
my_formula = [some_function(i) for i in range(10)]
print(my_formula)
# [2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0]


Y finalmente, puede usar el "si" para filtrar la lista. En este caso, guardamos solo aquellos valores que se dividen entre 2:



filtered = [i for i in range(20) if i%2==0]
print(filtered)
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]


3. Verifique el uso de memoria de sus objetos



Usando sys.getsizeof () puede verificar el uso de memoria de un objeto:



import sys

mylist = range(0, 10000)
print(sys.getsizeof(mylist))
# 48


Wow ... espera ... ¿por qué esta enorme lista pesa solo 48 bytes?

Esto se debe a que la función de rango devuelve una clase que solo se comporta como una lista. Un rango requiere mucha menos memoria que una lista real de números.

Puede verlo usted mismo mediante el uso de inclusiones de lista para crear una lista real de números del mismo rango:



import sys

myreallist = [x for x in range(0, 10000)]
print(sys.getsizeof(myreallist))
# 87632


Entonces, después de jugar sys.getsizeof(), puedes aprender más sobre Python y tu uso de memoria.



4. Clases de datos



A partir de la versión 3.7, Python ofrece clases de datos. Hay varias ventajas sobre las clases regulares u otras alternativas, como devolver múltiples valores o diccionarios:



  • la clase de datos requiere una cantidad mínima de código
  • puedes comparar clases de datos porque hay __eq__
  • puede derivar fácilmente una clase de datos para la depuración porque hay __repr__
  • las clases de datos requieren una sugerencia de tipo, lo que reduce la posibilidad de errores


Aquí hay un ejemplo de una clase de datos en acción:



from dataclasses import dataclass

@dataclass
class Card:
    rank: str
    suit: str
    
card = Card("Q", "hearts")

print(card == card)
# True

print(card.rank)
# 'Q'

print(card)
Card(rank='Q', suit='hearts')


Una guía detallada se puede encontrar aquí .



5. Atrs del paquete



Puede usar attrs en lugar de clases de datos . Hay dos razones para elegir attrs:



  • Estás utilizando una versión de Python anterior a 3.7
  • Quieres mas opciones


El paquete es attrscompatible con todas las versiones principales de Python, incluidas CPython 2.7 y PyPy. Algunos de los atributos adicionales que se ofrecen en attrscomparación con las clases de datos regulares son validadores y convertidores. Veamos un código de ejemplo:



@attrs
class Person(object):
    name = attrib(default='John')
    surname = attrib(default='Doe')
    age = attrib(init=False)
    
p = Person()
print(p)
p = Person('Bill', 'Gates')
p.age = 60
print(p)

# Output: 
#   Person(name='John', surname='Doe', age=NOTHING)
#   Person(name='Bill', surname='Gates', age=60)


Los autores attrsrealmente trabajaron en el PEP que introdujo las clases de datos. Las clases de datos se almacenan intencionalmente de manera más fácil (más fácil de entender), ¡mientras que attrs ofrece un conjunto completo de funciones que puede necesitar!



Se pueden encontrar más ejemplos en la página de ejemplos de attrs .



6. Combinando diccionarios (Python 3.5+)



Desde Python 3.5, es más fácil combinar diccionarios:



dict1 = { 'a': 1, 'b': 2 }
dict2 = { 'b': 3, 'c': 4 }
merged = { **dict1, **dict2 }
print (merged)
# {'a': 1, 'b': 3, 'c': 4}


Si hay claves de intersección, las claves del primer diccionario se sobrescribirán.



En Python 3.9, combinar diccionarios es aún más limpio. La fusión anterior en Python 3.9 se puede reescribir como:



merged = dict1 | dict2


7. Busque el valor más común.



Para encontrar el valor más común en una lista o línea:



test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]
print(max(set(test), key = test.count))
# 4


¿Entiendes por qué esto funciona? Intenta resolverlo por ti mismo antes de seguir leyendo.



Incluso lo intentaste, ¿no? Te diré de todos modos:



  • max()devolverá el valor más grande en la lista. El argumento keytoma una función de argumento único para personalizar el orden de clasificación, en este caso test.count. La función se aplica a cada elemento del iterable.
  • test.count- Función de lista incorporada. Toma un argumento y contará el número de ocurrencias para ese argumento. Entonces test.count(1)devolverá 2 y test.count(4)devolverá 4.
  • set(test) devuelve todos los valores únicos de la prueba, por lo que {1, 2, 3, 4}


Entonces, en esta única línea de código, aceptamos todos los valores únicos para una prueba que es {1, 2, 3, 4}. A continuación, les maxaplicará una función list.county devolverá el valor máximo.



Y no, no inventé esta frase.



Actualización: Varios comentaristas han señalado correctamente que hay una manera mucho más eficiente de hacer esto:



from collections import Counter
Counter(test).most_common(1)
# [4: 4]


8. Devolución de valores múltiples



Las funciones en Python pueden devolver más de una variable sin un diccionario, lista o clase. Funciona así:



def get_user(id):
    # fetch user from database
    # ....
    return name, birthdate

name, birthdate = get_user(4)


Esto está bien para un número limitado de valores de retorno. Pero cualquier cosa por encima de 3 valores debe colocarse en la clase (datos).



imagen



Aprenda los detalles de cómo obtener una profesión solicitada desde cero o subir de nivel en habilidades y salario completando los cursos en línea pagos de SkillFactory:











All Articles