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
attrs
prend en charge toutes les versions principales de Python, y compris CPython 2.7 et PyPy. Certains des attributs supplémentaires offerts attrs
par 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
attrs
fait 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'argumentkey
prend 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, iltest.count(1)
renvoie 2 ettest.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 max
appliquera une fonction list.count
et 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).
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:
- Machine Learning (12 )
- Data Science (12 )
- (9 )
- «Python -» (9 )