Python >> Tutoriel Python >  >> Python

Compréhension du dictionnaire Python :un puissant didacticiel en une seule ligne

Compréhension du dictionnaire est un moyen concis et économe en mémoire pour créer et initialiser des dictionnaires dans une ligne de code Python. Il se compose de deux parties :l'expression et le contexte. L'expression définit comment mapper les clés aux valeurs. Le contexte boucle sur un itérable à l'aide d'une boucle for sur une seule ligne et définit les paires (clé, valeur) à inclure dans le nouveau dictionnaire.

L'exemple suivant montre comment utiliser la compréhension du dictionnaire pour créer une correspondance de femmes à hommes :

men = ['Bob', 'Frank', 'Pete']
women = ['Alice', 'Ann', 'Liz']

# One-Liner Dictionary Comprehension
pairs = {w:m for w, m in zip(women, men)}

# Print the result to the shell
print(pairs)
# {'Bob': 'Alice', 'Frank': 'Ann', 'Pete': 'Liz'}

Ensuite, vous plongerez dans un court exercice Python pour ouvrir et combler vos lacunes dans les connaissances et renforcer votre compréhension intuitive.

Shell Python interactif

Exécutez la compréhension de dictionnaire à une ligne suivante dans le shell de code interactif :

Exercice :Modifiez le code afin que chaque valeur x corresponde à son cube x**3 pour les onze premières valeurs de 0 à 10 (inclus) !

Article connexe : Chaque maître Python a également maîtrisé la structure des données du dictionnaire. Consultez notre didacticiel complet sur le blog Finxter ici.

Ensuite, vous plongerez encore plus profondément dans le puissant opérateur de compréhension du dictionnaire, étape par étape !

Zip de compréhension du dictionnaire Python

La compréhension du dictionnaire vous permet de créer des dictionnaires de manière propre, facile à comprendre et Pythonique. Cependant, si vous avez deux listes, vous pouvez en créer un dictionnaire en utilisant dict(zip()) .

names = ['Adam', 'Beth', 'Charlie', 'Dani', 'Ethan']
countries = ['Argentina', 'Bulgaria', 'Colombia', 'Denmark', 'Estonia']
 
dict_zip = dict(zip(names, countries))
 
>>> dict_zip
{'Adam': 'Argentina',
'Beth': 'Bulgaria',
'Charlie': 'Colombia',
'Dani': 'Denmark',
'Ethan': 'Estonia'}

Vous pouvez également le faire en utilisant une boucle for

>>> new_dict = {}
>>> for name, country in zip(names, countries):
        new_dict[name] = country
 
>>> new_dict
{'Adam': 'Argentina',
'Beth': 'Bulgaria',
'Charlie': 'Colombia',
'Dani': 'Denmark',
'Ethan': 'Estonia'}

Vous initialisez vos variables dict et iterator avec des noms descriptifs. Pour itérer sur les deux listes en même temps, vous les compressez ensemble. Vous ajoutez des paires clé-valeur comme vous le souhaitez. Cela prend 3 lignes.

L'utilisation de la compréhension du dictionnaire transforme cela en une seule ligne ! ?

dict_comp = {name: country for name, country in zip(names, countries)}
 
>>> dict_comp
{'Adam': 'Argentina',
'Beth': 'Bulgaria',
'Charlie': 'Colombia',
'Dani': 'Denmark',
'Ethan': 'Estonia'}

Les compréhensions de dictionnaire sont un peu comme pour les boucles à l'envers . Tout d'abord, nous indiquons ce que nous voulons que nos paires clé-valeur soient. Ensuite, nous utilisons la même boucle for et enveloppons le tout dans des accolades.

Notez que chaque compréhension peut être écrite comme une boucle for. Si jamais vous obtenez des résultats auxquels vous ne vous attendiez pas, essayez-le comme une boucle for pour voir ce qui se passe.

Voici une erreur courante

dict_comp_bad = {name: country 
                 for name in names 
                 for country in countries}
 
>>> dict_comp_bad
{'Adam': 'Estonia',
'Beth': 'Estonia',
'Charlie': 'Estonia',
'Dani': 'Estonia',
'Ethan': 'Estonia'}

Que se passe-t-il? Écrivons-le comme une boucle for pour voir. Tout d'abord, nous allons l'écrire pour nous assurer que nous obtenons le même résultat indésirable.

bad_dict = {}
for name in names:
    for country in countries:
        bad_dict[name] = country
 
>>> bad_dict
{'Adam': 'Estonia',
'Beth': 'Estonia',
'Charlie': 'Estonia',
'Dani': 'Estonia',
'Ethan': 'Estonia'}

Nous allons maintenant utiliser le meilleur ami du chercheur de bogues :la déclaration d'impression !

# Don't initialise dict to just check for loop logic
for name in names:
    for country in countries:
        print(name, country)
Adam Argentina
Adam Bulgaria
Adam Colombia
Adam Denmark
Adam Estonia
Beth Argentina
Beth Bulgaria
Beth Colombia
...
Ethan Colombia
Ethan Denmark
Ethan Estonia

Ici, nous supprimons le dictionnaire pour vérifier ce qui se passe réellement dans la boucle. Maintenant, nous voyons le problème! Le problème est que nous avons boucles imbriquées . La boucle dit :pour chaque nom, associez-le à chaque pays. Étant donné que les clés de dictionnaire ne peuvent qu'apparaître, la valeur est écrasée à chaque itération. Ainsi, la valeur de chaque clé est la dernière qui apparaît dans la boucle - 'Estonia' .

La solution consiste à supprimer les boucles for imbriquées et à utiliser zip() Au lieu.

Dictionnaires imbriqués Python avec compréhensions de dictionnaire

nums = [0, 1, 2, 3, 4, 5]
 
dict_nums = {n: {'even': n % 2 == 0,
                 'square': n**2,
                 'cube': n**3,
                 'square_root': n**0.5}
             for n in nums}
 
# Pretty print for ease of reading
>>> pprint(dict_nums)
{0: {'cube': 0, 'even': True, 'square': 0, 'square_root': 0.0},
1: {'cube': 1, 'even': False, 'square': 1, 'square_root': 1.0},
2: {'cube': 8, 'even': True, 'square': 4, 'square_root': 1.4142135623730951},
3: {'cube': 27, 'even': False, 'square': 9, 'square_root': 1.7320508075688772},
4: {'cube': 64, 'even': True, 'square': 16, 'square_root': 2.0},
5: {'cube': 125, 'even': False, 'square': 25, 'square_root': 2.23606797749979}}

C'est là que les compréhensions deviennent puissantes. Nous définissons un dictionnaire dans un dictionnaire pour créer beaucoup d'informations en quelques lignes de code. La syntaxe est exactement la même que ci-dessus mais notre valeur est plus complexe que le premier exemple.

N'oubliez pas que nos paires clé-valeur doivent être uniques et nous ne pouvons donc pas créer un dictionnaire comme celui-ci

>>> nums = [0, 1, 2, 3, 4, 5]
>>> wrong_dict = {'number': num, 'square': num ** 2 for num in nums}
  File "<stdin>", line 1
    wrong_dict = {'number': num, 'square': num ** 2 for num in nums}
                                                    ^
SyntaxError: invalid syntax

Nous ne pouvons définir qu'un seul modèle pour les paires clé-valeur dans une compréhension. Mais si vous pouviez définir plus, cela ne serait pas très utile. Nous écraserions nos paires clé-valeur à chaque itération car les clés doivent être uniques.

Instructions Si-Elif-Sinon

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
# Just the even numbers
even_squares = {n: n ** 2 for n in nums
                if n % 2 == 0}
 
# Just the odd numbers
odd_squares = {n: n ** 2 for n in nums
               if n % 2 == 1}
 
>>> even_dict
{0: 0, 2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
 
>>> odd_dict
{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}

Nous pouvons appliquer des conditions if après l'instruction for. Cela affecte toutes les valeurs sur lesquelles vous itérez.

Vous pouvez également les appliquer à vos définitions de clé et de valeur. Nous allons maintenant créer différentes paires clé-valeur selon qu'un nombre est pair ou impair.

# Use parenthesis to aid readability
different_vals = {n: ('even' if n % 2 == 0 else 'odd')
                  for n in range(5)}
 
>>> different_vals
{0: 'even', 1: 'odd', 2: 'even', 3: 'odd', 4: 'even'}

Nous pouvons devenir très complexes et utiliser des instructions if/else à la fois dans les définitions de clé-valeur et après la boucle for !

# Change each key using an f-string
{(f'{n}_cubed' if n % 2 == 1 else f'{n}_squared'): 
 
# Cube odd numbers, square even numbers
 (n ** 3 if n % 2 == 1 else n ** 2)
 
# The numbers 0-10 inclusive
 for n in range(11)
 
# If they are not multiples of 3
 if n % 3 != 0}
 
{'1_cubed': 1, '2_squared': 4, '4_squared': 16, '5_cubed': 125, '7_cubed': 343, '8_squared': 64, '10_squared': 100}

Il est relativement simple de le faire en utilisant des compréhensions. Essayer de le faire avec une boucle for ou dict() constructeur serait beaucoup plus difficile.

Formulations alternatives

Les deux déclarations sont en fait sémantiquement identiques :

dict([(i, chr(65+i)) for i in range(4)])

Est identique à :

{i : chr(65+i) for i in range(4)}

Exemples

Considérons cinq exemples de compréhensions de dictionnaires pour renforcer votre compréhension ! Les exemples sont des versions améliorées et simplifiées du code donné ici.

Exemple de compréhension de dictée 1

Problème :crée un dict compréhension à partir d'une liste d'entiers.

# Example 1:
# (key, value) --> (string, int)
print({str(i):i for i in range(5)})
# {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}

Chaque entier i est d'abord converti en chaîne en utilisant le str() fonction de conversion. Le mappage résultant de str(i) à i est ensuite stocké dans le dictionnaire pour toutes les valeurs entières i en 0, 1, 2, 3 et 4.

Exemple de compréhension de dictée 2

Problème :Étant donné une liste de noms de fruits sous forme de chaînes. Utilisez la compréhension dict pour créer un dictionnaire avec les éléments de la liste comme clés et leur longueur comme valeurs.

# Example 2:
fruits = ['apple', 'mango', 'banana','cherry']
d = {fruit:len(fruit) for fruit in fruits}
print(d)
# {'apple': 5, 'mango': 5, 'banana': 6, 'cherry': 6}

Vous parcourez chaque fruit de la liste. Ensuite, vous mappez chaque chaîne de fruits à sa longueur en utilisant le len() intégré de Python fonction qui compte le nombre de caractères dans la chaîne.

Exemple de compréhension de dictée 3

Problème  :Créez un dictionnaire avec compréhension dict avec des éléments de liste comme clés et leurs variantes en majuscules comme valeurs.

# Example 3:
d = {fruit:fruit.capitalize() for fruit in fruits}
print(d)
# {'apple': 'Apple', 'mango': 'Mango', 'banana': 'Banana', 'cherry': 'Cherry'}

Le string.capitalize() la fonction ne met en majuscule que la première lettre du string donné .

Exemple de compréhension de dictée 4

Problème :Utilisez le enumerate() fonction sur une liste pour créer des tuples (i, x) pour le poste i de l'élément x . Utilisez la compréhension dict avec des éléments de liste comme clés et leurs indices comme valeurs.

# Example 4:
d = {f:i for i,f in enumerate(fruits)}
print(d)
# {'apple': 0, 'mango': 1, 'banana': 2, 'cherry': 3}

Le enumerate(fruits) la fonction renvoie le (index, element) paires de fruits itérables . Vous attrapez le premier dans la variable i et ce dernier dans la variable f . Maintenant, vous inversez le mappage via f:i .

Exemple de compréhension de dictée 5

Problème :Inverser le (key, value ) mappages d'un dictionnaire donné. Grosso modo, vous souhaitez obtenir des mappages (valeur, clé), bien que les anciennes valeurs doivent être considérées comme les nouvelles clés !

# Example 5:
# Original dictionary:
d = {str(i): i for i in range(5)}
print(d)
# {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}

# Reversed dictionary:
d_r = {v:k for k,v in d.items()}
print(d_r)
# {0: '0', 1: '1', 2: '2', 3: '3', 4: '4'}

Vous utilisez le dict.items() fonction pour retourner les paires (clé, valeur) du dictionnaire d'origine d .


Terminons avec un shell de code interactif pour l'essayer vous-même :

Exercice :Modifiez chaque énoncé de compréhension du dictionnaire en changeant au moins une chose !

Ressources externes

Ce tutoriel est basé sur diverses ressources et sources en ligne.

  • https://www.python.org/dev/peps/pep-0274/
  • https://www.datacamp.com/community/tutorials/python-dictionary-comprehension
  • https://cmdlinetips.com/2018/01/5-examples-using-dict-comprehension/
  • https://stackoverflow.com/questions/14507591/python-dictionary-comprehension