8 astuces Python utilisées par des programmeurs expérimentés

image



Voici huit astuces Python que vous n'avez sûrement pas encore vues. Appliquez ces astuces à votre code Python pour le rendre plus concis et performant!



1. Tri des objets par plusieurs clés



Supposons que nous voulions trier la liste suivante de dictionnaires:



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 },
]


Mais nous ne voulons pas seulement les trier par nom ou par âge, nous voulons les trier par les deux champs. En SQL, ce serait une requête comme celle-ci:



SELECT * FROM people ORDER by name, age


En fait, il existe une solution très simple à ce problème, grâce à la garantie de Python que les fonctions de tri assurent la stabilité du tri . Cela signifie que les éléments comparés conservent leur ordre d'origine.



Pour effectuer un tri par nom et par âge, nous pouvons procéder comme suit:



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


Remarquez comment j'ai changé la commande. Nous trions d'abord par âge, puis par nom. Avec l'aide, operator.itemgetter()nous obtenons les champs d'âge et de nom de chaque dictionnaire de la liste.



Cela nous donne le résultat que nous voulions:



[
 {'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}
]


Les noms sont triés en premier, l'âge est trié si le nom correspond. Ainsi, tous les Johns sont regroupés par âge.



La source d'inspiration est une question de StackOverflow .



2. Inclusions de liste (générateur de liste)



Les inclusions de liste peuvent remplacer les boucles laides utilisées pour remplir la liste. Syntaxe de base pour les inclusions de liste:



[ expression for item in list if conditional ]


Un exemple très simple pour remplir une liste avec une séquence de nombres:



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


Et puisque vous pouvez utiliser une expression, vous pouvez également faire quelques calculs:



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


Ou même appeler une fonction externe:



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]


Enfin, vous pouvez utiliser "if" pour filtrer la liste. Dans ce cas, nous ne stockons que les valeurs divisibles par 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. Vérifiez l'utilisation de la mémoire de vos objets



En utilisant sys.getsizeof (), vous pouvez vérifier l'utilisation de la mémoire d'un objet:



import sys

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


Wow ... attendez ... pourquoi cette énorme liste ne fait-elle que 48 octets?

En effet, la fonction range renvoie une classe qui se comporte uniquement comme une liste. Une plage est beaucoup moins gourmande en mémoire qu'une liste réelle de nombres.

Vous pouvez le constater par vous-même en utilisant les listes d'inclusion pour créer une liste réelle de numéros de la même plage:



import sys

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


Ainsi, après avoir joué avec sys.getsizeof(), vous pouvez en savoir plus sur Python et votre utilisation de la mémoire.



4. Classes de données



À partir de la version 3.7, Python propose des classes de données. Il existe plusieurs avantages par rapport aux classes régulières ou à d'autres alternatives, comme le renvoi de plusieurs valeurs ou dictionnaires:



  • la classe de données nécessite une quantité minimale de code
  • vous pouvez comparer des classes de données car il y a __eq__
  • vous pouvez facilement dériver une classe de données pour le débogage car il y a __repr__
  • les classes de données nécessitent une indication de type, ce qui réduit le risque d'erreurs


Voici un exemple de classe de données en fonctionnement:



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')


Un guide détaillé peut être trouvé ici .



5. Paquet attrs



Vous pouvez utiliser des attrs au lieu de classes de données . Il y a deux raisons de choisir attrs:



  • Vous utilisez une version Python antérieure à 3.7
  • Vous voulez plus d'options


Le package attrsprend en charge toutes les versions principales de Python, y compris CPython 2.7 et PyPy. Certains des attributs supplémentaires offerts attrspar rapport aux classes de données ordinaires sont des validateurs et des convertisseurs. Regardons un exemple de code:



@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)


Les auteurs ont en attrsfait travaillé sur PEP, qui a introduit des classes de données. Les classes de données sont délibérément simplifiées (plus faciles à comprendre), tandis que attrs offre un ensemble complet de fonctionnalités dont vous pourriez avoir besoin!



Plus d'exemples peuvent être trouvés sur la page d'exemples attrs .



6. Combinaison de dictionnaires (Python 3.5+)



À partir de Python 3.5, il est plus facile de combiner des dictionnaires:



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


S'il y a des clés qui se croisent, les clés du premier dictionnaire seront écrasées.



Dans Python 3.9, la combinaison de dictionnaires est encore plus propre. La fusion ci-dessus dans Python 3.9 peut être réécrite comme:



merged = dict1 | dict2


7. Recherchez le sens le plus courant



Pour rechercher la valeur la plus courante dans une liste ou une chaîne:



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


Comprenez-vous pourquoi cela fonctionne? Essayez de le découvrir par vous-même avant de continuer à lire.



Vous avez même essayé, non? Je vais quand même vous dire:



  • max()renverra la valeur la plus élevée de la liste. L'argument keyprend une fonction d'argument unique pour personnaliser l'ordre de tri, dans ce cas test.count. La fonction est appliquée à chaque élément de l'itérable.
  • test.count- fonction de liste intégrée. Il prend un argument et comptera le nombre d'occurrences pour cet argument. Ainsi, il test.count(1)renvoie 2 et test.count(4)renvoie 4.
  • set(test) renvoie toutes les valeurs uniques du test, donc {1, 2, 3, 4}


Donc, dans cette seule ligne de code, nous prenons toutes les valeurs uniques du test, qui est égal {1, 2, 3, 4}. Ensuite, il leur maxappliquera une fonction list.countet renverra la valeur maximale.



Et non - je n'ai pas inventé ce one-liner.



Mise à jour: Un certain nombre de commentateurs ont noté à juste titre qu'il existe un moyen beaucoup plus efficace de le faire:



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


8. Renvoyer plusieurs valeurs



Les fonctions en Python peuvent renvoyer plusieurs variables sans dictionnaire, liste ou classe. Cela fonctionne comme ceci:



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

name, birthdate = get_user(4)


Cela convient pour un nombre limité de valeurs de retour. Mais tout ce qui dépasse 3 valeurs doit être placé dans la classe (data).



image



Apprenez comment obtenir une profession recherchée à partir de zéro ou augmenter vos compétences et votre salaire en suivant des cours en ligne payés par SkillFactory:











All Articles