Expert Python
Un problème courant que vous pouvez rencontrer lorsque vous travaillez avec des dictionnaires Python est d'essayer d'accéder ou de modifier des clés qui n'existent pas dans le dictionnaire. Cela soulèvera un KeyError
et briser l'exécution de votre code. Pour gérer ce genre de situations, la bibliothèque standard fournit le Python defaultdict
type, une classe de type dictionnaire qui est disponible pour vous dans collections
.
Le Python defaultdict
se comporte presque exactement comme un dictionnaire Python standard, mais si vous essayez d'accéder ou de modifier une clé manquante, defaultdict
crée automatiquement la clé et génère une valeur par défaut pour celle-ci. Cela fait defaultdict
une option précieuse pour gérer les clés manquantes dans les dictionnaires.
Dans ce didacticiel, vous apprendrez:
- Comment utiliser le Python
defaultdict
taper pour gestion des clés manquantes dans un dictionnaire - Quand et pourquoi utiliser un Python
defaultdict
plutôt qu'un habituédicter
- Comment utiliser un
defaultdict
pour regroupement, compte, et accumuler opérations
Avec ces connaissances à votre disposition, vous serez en meilleure condition pour utiliser efficacement le Python defaultdict
tapez vos défis de programmation au jour le jour.
Pour tirer le meilleur parti de ce didacticiel, vous devez avoir une compréhension préalable de ce que sont les dictionnaires Python et comment les utiliser. Si vous avez besoin de vous rafraîchir, consultez les ressources suivantes:
Gestion des clés manquantes dans les dictionnaires
Un problème courant que vous pouvez rencontrer lorsque vous travaillez avec des dictionnaires Python est comment gérer les clés manquantes. Si votre code est fortement basé sur des dictionnaires, ou si vous créez des dictionnaires à la volée tout le temps, vous remarquerez bientôt que le traitement des KeyError
les exceptions peuvent être assez ennuyeuses et peuvent ajouter une complexité supplémentaire à votre code. Avec les dictionnaires Python, vous avez au moins quatre façons disponibles de gérer les clés manquantes:
- Utilisation
.définir par defaut()
- Utilisation
.avoir()
- Utilisez le
entrer le dict
idiome - Utiliser un
essayer
etsauf
bloquer
Les documents Python expliquent .définir par defaut()
et .avoir()
comme suit:
setdefault (clé[, default])
Si
clé
est dans le dictionnaire, retourne sa valeur. Sinon, insérezclé
avec une valeur dedéfaut
et retourdéfaut
.défaut
par défaut àAucun
.
Obtenir la clé[, default])
Renvoie la valeur de
clé
siclé
est dans le dictionnaire, sinondéfaut
. Sidéfaut
n'est pas donné, il est par défautAucun
, de sorte que cette méthode ne soulève jamaisKeyError
.(La source)
Voici un exemple d'utilisation .définir par defaut()
gérer les clés manquantes dans un dictionnaire:
>>> a_dict =
>>> a_dict[[[['missing_key']
Traceback (dernier appel le plus récent):
Fichier "" , ligne 1, dans
a_dict[[[['missing_key']
KeyError: 'missing_key'
>>> a_dict.définir par defaut('missing_key', 'valeur par défaut')
'valeur par défaut'
>>> a_dict[[[['missing_key']
'valeur par défaut'
>>> a_dict.définir par defaut('missing_key', «une autre valeur par défaut»)
'valeur par défaut'
>>> a_dict
'missing_key': 'valeur par défaut'
Dans le code ci-dessus, vous utilisez .définir par defaut()
pour générer une valeur par défaut pour clé_ manquante
. Notez que votre dictionnaire, a_dict
, a maintenant une nouvelle clé appelée clé_ manquante
dont la valeur est 'valeur par défaut'
. Cette clé n'existait pas avant que vous ayez appelé .définir par defaut()
. Enfin, si vous appelez .définir par defaut()
sur une clé existante, l'appel n'aura aucun effet sur le dictionnaire. Votre clé contiendra la valeur d'origine au lieu de la nouvelle valeur par défaut.
Remarque: Dans l'exemple de code ci-dessus, vous obtenez une exception et Python vous montre un traceback message, qui vous indique que vous essayez d'accéder à une clé manquante dans a_dict
. Si vous souhaitez approfondir la façon de déchiffrer et de comprendre un traçage Python, consultez la section Comprendre le traçage Python.
En revanche, si vous utilisez .avoir()
, vous pouvez alors coder quelque chose comme ceci:
>>> a_dict =
>>> a_dict.avoir('missing_key', 'valeur par défaut')
'valeur par défaut'
>>> a_dict
Ici, vous utilisez .avoir()
pour générer une valeur par défaut pour clé_ manquante
, mais cette fois, votre dictionnaire reste vide. Ceci est dû au fait .avoir()
renvoie la valeur par défaut, mais cette valeur n'est pas ajoutée au dictionnaire sous-jacent. Par exemple, si vous avez un dictionnaire appelé ré
, alors vous pouvez supposer que .avoir()
fonctionne quelque chose comme ceci:
D.get (clé, par défaut) -> D[key] si clé en D, sinon par défaut
Avec ce pseudo-code, vous pouvez comprendre comment .avoir()
travaille en interne. Si la clé existe, alors .avoir()
renvoie la valeur mappée à cette clé. Sinon, la valeur par défaut est retournée. Votre code ne crée ni n'attribue jamais de valeur à clé
. Dans cet exemple, défaut
par défaut à Aucun
.
Vous pouvez également utiliser des instructions conditionnelles pour gérer les clés manquantes dans les dictionnaires. Jetez un œil à l'exemple suivant, qui utilise le entrer le dict
idiome:
>>> a_dict =
>>> si 'clé' dans a_dict:
... # Faites quelque chose avec 'clé' ...
... a_dict[[[['clé']
... autre:
... a_dict[[[['clé'] = 'valeur par défaut'
...
>>> a_dict
'clé': 'valeur par défaut'
Dans ce code, vous utilisez un si
déclaration avec le dans
opérateur pour vérifier si clé
est présent dans a_dict
. Si c'est le cas, vous pouvez effectuer n'importe quelle action avec clé
ou avec sa valeur. Sinon, vous créez la nouvelle clé, clé
et lui attribuer un 'valeur par défaut'
. Notez que le code ci-dessus fonctionne de manière similaire à .définir par defaut()
mais prend quatre lignes de code, tandis que .définir par defaut()
ne prendrait qu'une seule ligne (en plus d'être plus lisible).
Vous pouvez également vous promener KeyError
en utilisant un essayer
et sauf
bloc pour gérer l'exception. Considérez le morceau de code suivant:
>>> a_dict =
>>> essayer:
... # Faites quelque chose avec 'clé' ...
... a_dict[[[['clé']
... sauf KeyError:
... a_dict[[[['clé'] = 'valeur par défaut'
...
>>> a_dict
'clé': 'valeur par défaut'
le essayer
et sauf
bloc dans l'exemple ci-dessus attrape le KeyError
chaque fois que vous essayez d'accéder à une clé manquante. dans le sauf
clause, vous créez le clé
et lui attribuer un 'valeur par défaut'
.
Remarque: Si les clés manquantes sont rares dans votre code, vous préférerez peut-être utiliser un essayer
et sauf
bloc (style de codage EAFP) pour attraper le KeyError
exception. En effet, le code ne vérifie pas l’existence de chaque clé et ne gère que quelques exceptions, le cas échéant.
En revanche, si les clés manquantes sont assez courantes dans votre code, l'instruction conditionnelle (style de codage LBYL) peut être un meilleur choix car la recherche de clés peut être moins coûteuse que la gestion d'exceptions fréquentes.
Jusqu'à présent, vous avez appris à gérer les clés manquantes à l'aide des outils dicter
et Python vous offre. Cependant, les exemples que vous avez vus ici sont assez verbeux et difficiles à lire. Ils peuvent ne pas être aussi simples que vous le souhaitez. C'est pourquoi la bibliothèque standard Python fournit une solution plus élégante, Pythonique et efficace. Cette solution est collections.defaultdict
, et c'est ce que vous allez couvrir désormais.
Comprendre le Python defaultdict
Type
La bibliothèque standard Python fournit collections
, qui est un module qui implémente des types de conteneurs spécialisés. L'un d'eux est le Python defaultdict
type, qui est une alternative à dicter
spécialement conçu pour vous aider avec les clés manquantes. defaultdict
est un type Python qui hérite de dicter
:
>>> de collections importation defaultdict
>>> issubclass(defaultdict, dicter)
Vrai
Le code ci-dessus montre que le Python defaultdict
le type est un sous-classe de dicter
. Cela signifie que defaultdict
hérite de la plupart du comportement de dicter
. Vous pouvez donc dire que defaultdict
ressemble beaucoup à un dictionnaire ordinaire.
La principale différence entre defaultdict
et dicter
est que lorsque vous essayez d'accéder ou de modifier un clé
qui n'est pas présent dans le dictionnaire, une valeur par défaut valeur
est automatiquement attribué à cette clé
. Afin de fournir cette fonctionnalité, le Python defaultdict
type fait deux choses:
- Il remplace
.__disparu__()
. - Il ajoute
.default_factory
, une variable d'instance accessible en écriture qui doit être fournie au moment de l'instanciation.
La variable d'instance .default_factory
contiendra le premier argument passé dans defaultdict .__ init __ ()
. Cet argument peut prendre un appelable Python valide ou Aucun
. Si un appelable est fourni, il sera automatiquement appelé par defaultdict
chaque fois que vous essayez d'accéder ou de modifier la valeur associée à une clé manquante.
Remarque: Tous les arguments restants de l'initialiseur de classe sont traités comme s'ils étaient passés à l'initialiseur de regular dicter
, y compris les arguments du mot clé.
Découvrez comment créer et initialiser correctement un defaultdict
:
>>> # Instanciation correcte
>>> def_dict = defaultdict(liste) # Passer la liste à .default_factory
>>> def_dict[[[['un'] = 1 # Ajouter une paire valeur / clé
>>> def_dict[[[['disparu'] # Accéder à une clé manquante renvoie une liste vide
[]
>>> def_dict[[[['another_missing'].ajouter(4) # Modifier une clé manquante
>>> def_dict
defaultdict (, 'un': 1, 'manquant': [], 'another_missing': [4])
Ici, tu passes liste
à .default_factory
lorsque vous créez le dictionnaire. Ensuite, vous utilisez def_dict
comme un dictionnaire ordinaire. Notez que lorsque vous essayez d'accéder ou de modifier la valeur mappée à une clé inexistante, le dictionnaire lui attribue la valeur par défaut résultant de l'appel liste()
.
Gardez à l'esprit que vous devez transmettre un objet appelable Python valide à .default_factory
, n'oubliez donc pas de l'appeler en utilisant les parenthèses au moment de l'initialisation. Cela peut être un problème courant lorsque vous commencez à utiliser Python defaultdict
type. Jetez un œil au code suivant:
>>> # Mauvaise instanciation
>>> def_dict = defaultdict(liste())
Traceback (dernier appel le plus récent):
Fichier "" , ligne 1, dans
def_dict = defaultdict(liste())
Erreur-type: le premier argument doit pouvoir être appelé ou Aucun
Ici, vous essayez de créer un defaultdict
en passant liste()
à .default_factory
. L'appel à liste()
soulève un Erreur-type
, qui vous indique que le premier argument doit être appelable ou Aucun
.
Avec cette introduction au Python defaultdict
tapez, vous pouvez commencer à coder avec des exemples pratiques. Les sections suivantes vous guideront à travers quelques cas d’utilisation courants où vous pouvez defaultdict
pour fournir une solution élégante, efficace et Pythonique.
Utiliser le Python defaultdict
Type
Parfois, vous utiliserez une collection intégrée mutable (un liste
, dicter
, ou ensemble
) comme valeurs dans vos dictionnaires Python. Dans ces cas, vous devrez initialiser les clés avant la première utilisation, ou vous obtiendrez un KeyError
. Vous pouvez soit faire ce processus manuellement ou l'automatiser à l'aide d'un Python defaultdict
. Dans cette section, vous apprendrez à utiliser Python defaultdict
type pour résoudre certains problèmes de programmation courants:
- Regroupement les éléments d'une collection
- Compte les éléments d'une collection
- Accumuler les valeurs d'une collection
Vous couvrirez quelques exemples qui utilisent liste
, ensemble
, int
, et flotte
pour effectuer des opérations de regroupement, de comptage et d'accumulation de manière conviviale et efficace.
Regroupement d'éléments
Une utilisation typique du Python defaultdict
le type est à définir .default_factory
à liste
puis créez un dictionnaire qui mappe les clés aux listes de valeurs. Avec ça defaultdict
, si vous essayez d'accéder à une clé manquante, le dictionnaire exécute les étapes suivantes:
- Appel
liste()
pour créer un nouveau videliste
- Insérer le vide
liste
dans le dictionnaire en utilisant la clé manquante commeclé
- Revenir une référence à cela
liste
Cela vous permet d'écrire du code comme ceci:
>>> de collections importation defaultdict
>>> dd = defaultdict(liste)
>>> dd[[[['clé'].ajouter(1)
>>> dd
defaultdict (, 'clé': [1])
>>> dd[[[['clé'].ajouter(2)
>>> dd
defaultdict (, 'clé': [1, 2])
>>> dd[[[['clé'].ajouter(3)
>>> dd
defaultdict (, 'clé': [1, 2, 3])
Ici, vous créez un Python defaultdict
appelé dd
et passer liste
à .default_factory
. Notez que même lorsque clé
n'est pas défini, vous pouvez y ajouter des valeurs sans obtenir de KeyError
. C'est parce que dd
appelle automatiquement .default_factory
pour générer une valeur par défaut pour le manquant clé
.
Vous pouvez utiliser defaultdict
de même que liste
pour regrouper les éléments dans une séquence ou une collection. Supposons que vous ayez récupéré les données suivantes de la base de données de votre entreprise:
département | Nom de l'employé |
---|---|
Ventes | John Doe |
Ventes | Martin Smith |
Comptabilité | Jane Doe |
Commercialisation | Elizabeth Smith |
Commercialisation | Adam Doe |
… | … |
Avec ces données, vous créez une première liste
de tuple
des objets comme les suivants:
dep = [([([([('Ventes', «John Doe»),
('Ventes', «Martin Smith»),
('Comptabilité', 'Jane Doe'),
('Commercialisation', «Elizabeth Smith»),
('Commercialisation', «Adam Doe»)]
Maintenant, vous devez créer un dictionnaire qui regroupe les employés par service. Pour ce faire, vous pouvez utiliser un defaultdict
comme suit:
de collections importation defaultdict
dep_dd = defaultdict(liste)
pour département, employé dans dep:
dep_dd[[[[département].ajouter(employé)
Ici, vous créez un defaultdict
appelé dep_dd
et utiliser un pour
boucle pour parcourir votre dep
liste. La déclaration dep_dd[department].append (employé)
crée les clés des départements, les initialise dans une liste vide, puis ajoute les employés à chaque département. Une fois que vous avez exécuté ce code, votre dep_dd
ressemblera à ceci:
defaultdict (, 'Ventes': ['John Doe', 'Martin Smith'],
'Comptabilité' : ['Jane Doe'],
'Commercialisation': ['Elizabeth Smith', 'Adam Doe'])
Dans cet exemple, vous regroupez les employés par service en utilisant un defaultdict
avec .default_factory
mis à liste
. Pour ce faire avec un dictionnaire standard, vous pouvez utiliser dict.setdefault ()
comme suit:
dep_d = dicter()
pour département, employé dans dep:
dep_d.définir par defaut(département, []).ajouter(employé)
Ce code est simple et vous trouverez assez souvent du code similaire dans votre travail de codeur Python. Cependant, le defaultdict
La version est sans doute plus lisible, et pour les grands ensembles de données, elle peut également être beaucoup plus rapide et plus efficace. Donc, si la vitesse vous préoccupe, vous devriez envisager d'utiliser un defaultdict
au lieu d'une norme dicter
.
Regroupement d'articles uniques
Continuez à travailler avec les données des départements et des employés de la section précédente. Après un certain traitement, vous vous rendez compte que quelques employés ont été dupliqué dans la base de données par erreur. Vous devez nettoyer les données et supprimer les employés en double de votre dep_dd
dictionnaire. Pour ce faire, vous pouvez utiliser un ensemble
comme le .default_factory
et réécrivez votre code comme suit:
dep = [([([([('Ventes', «John Doe»),
('Ventes', «Martin Smith»),
('Comptabilité', 'Jane Doe'),
('Commercialisation', «Elizabeth Smith»),
('Commercialisation', «Elizabeth Smith»),
('Commercialisation', «Adam Doe»),
('Commercialisation', «Adam Doe»),
('Commercialisation', «Adam Doe»)]
dep_dd = defaultdict(ensemble)
pour département, employé dans articles:
dep_dd[[[[département].ajouter(employé)
Dans cet exemple, vous définissez .default_factory
à ensemble
. Ensembles sont collections d'objets uniques, ce qui signifie que vous ne pouvez pas créer un ensemble
avec des éléments répétés. Il s'agit d'une fonctionnalité très intéressante des ensembles, qui garantit que vous n'aurez pas d'éléments répétés dans votre dictionnaire final.
Compter les articles
Si vous définissez .default_factory
à int
, alors votre defaultdict
sera utile pour compter les articles dans une séquence ou une collection. Quand vous appelez int ()
sans arguments, la fonction retourne 0
, qui est la valeur typique que vous utilisez pour initialiser un compteur.
Pour continuer avec l'exemple de la base de données de l'entreprise, supposons que vous souhaitiez créer un dictionnaire qui compte le nombre d'employés par service. Dans ce cas, vous pouvez coder quelque chose comme ceci:
>>> de collections importation defaultdict
>>> dep = [([([([('Ventes', «John Doe»),
... ('Ventes', «Martin Smith»),
... ('Comptabilité', 'Jane Doe'),
... ('Commercialisation', «Elizabeth Smith»),
... ('Commercialisation', «Adam Doe»)]
>>> dd = defaultdict(int)
>>> pour département, _ dans dep:
... dd[[[[département] + = 1
>>> dd
defaultdict (, 'Ventes': 2, 'Comptabilité': 1, 'Marketing': 2)
Ici, vous définissez .default_factory
à int
. Quand vous appelez int ()
sans argument, la valeur renvoyée est 0
. Vous pouvez utiliser cette valeur par défaut pour commencer à compter les employés qui travaillent dans chaque service. Pour que ce code fonctionne correctement, vous avez besoin d'un ensemble de données propre. Il ne doit pas y avoir de données répétées. Sinon, vous devrez filtrer les employés répétés.
Un autre exemple de comptage des éléments est le Mississippi
exemple, où vous comptez le nombre de fois que chaque lettre d'un mot est répétée. Jetez un œil au code suivant:
>>> de collections importation defaultdict
>>> s = 'Mississippi'
>>> dd = defaultdict(int)
>>> pour lettre dans s:
... dd[[[[lettre] + = 1
...
>>> dd
defaultdict (, 'm': 1, 'i': 4, 's': 4, 'p': 2)
Dans le code ci-dessus, vous créez un defaultdict
avec .default_factory
mis à int
. Cela définit la valeur par défaut d'une clé donnée sur 0
. Ensuite, vous utilisez un pour
boucle pour parcourir la chaîne s
et utiliser une opération d'affectation augmentée pour ajouter 1
au comptoir à chaque itération. Les clés de dd
seront les lettres Mississippi
.
Remarque: Les opérateurs d'affectation augmentée de Python sont un raccourci pratique pour les opérations courantes.
Jetez un œil aux exemples suivants:
var + = 1
est équivalent àvar = var + 1
var - = 1
est équivalent àvar = var - 1
var * = 1
est équivalent àvar = var * 1
Ceci n'est qu'un exemple du fonctionnement des opérateurs d'affectation augmentée. Vous pouvez consulter la documentation officielle pour en savoir plus sur cette fonctionnalité.
Comme le comptage est une tâche relativement courante en programmation, la classe de type dictionnaire Python collections.Counter
est spécialement conçu pour compter les articles dans une séquence. Avec Compteur
, vous pouvez écrire le Mississippi
exemple comme suit:
>>> de collections importation Compteur
>>> compteur = Compteur('Mississippi')
>>> compteur
Compteur ('i': 4, 's': 4, 'p': 2, 'm': 1)
Dans ce cas, Compteur
fait tout le travail pour vous! Vous n'avez qu'à passer dans une séquence, et le dictionnaire comptera ses éléments, les stockant comme clés et les comptes comme valeurs. Notez que cet exemple fonctionne car les chaînes Python sont également un type de séquence.
Accumuler des valeurs
Parfois, vous devrez calculer le somme totale des valeurs dans une séquence ou une collection. Supposons que vous ayez la feuille Excel suivante avec des données sur les ventes de votre site Web Python:
Des produits | juillet | août | septembre |
---|---|---|---|
Livres | 1250,00 | 1300,00 | 1420,00 |
Tutoriels | 560,00 | 630,00 | 750,00 |
Cours | 2500,00 | 2430.00 | 2750,00 |
Ensuite, vous traitez les données à l'aide de Python et obtenez les éléments suivants liste
de tuple
objets:
revenus = [([([([('Livres', 1250,00),
('Livres', 1300,00),
('Livres', 1420,00),
('Tutoriels', 560,00),
('Tutoriels', 630,00),
('Tutoriels', 750,00),
('Cours', 2500,00),
('Cours', 2430.00),
('Cours', 2750,00),]
Avec ces données, vous souhaitez calculer le revenu total par produit. Pour ce faire, vous pouvez utiliser un Python defaultdict
avec flotte
comme .default_factory
puis coder quelque chose comme ceci:
1 de collections importation defaultdict
2
3 dd = defaultdict(flotte)
4 pour produit, le revenu dans revenus:
5 dd[[[[produit] + = le revenu
6
sept pour produit, le revenu dans dd.articles():
8 impression(F«Revenu total pour produit: $revenus:,. 2f")
Voici ce que fait ce code:
- En ligne 1, vous importez le Python
defaultdict
type. - En ligne 3, vous créez un
defaultdict
objet avec.default_factory
mis àflotte
. - En ligne 4, vous définissez un
pour
boucle pour parcourir les éléments derevenus
. - En ligne 5, vous utilisez une opération d'affectation augmentée (
+ =
) pour accumuler les revenus par produit dans le dictionnaire.
La deuxième boucle parcourt les éléments de dd
et imprime les revenus sur votre écran.
Si vous mettez tout ce code dans un fichier appelé revenus.py
et l'exécuter à partir de votre ligne de commande, vous obtiendrez la sortie suivante:
$ python3 revenus.py
Revenu total pour les livres: 3 970,00 $
Revenu total pour les tutoriels: 1 940,00 $
Revenu total pour les cours: 7 680,00 $
Vous avez maintenant un résumé des revenus par produit, vous pouvez donc prendre des décisions sur la stratégie à suivre pour augmenter le revenu total de votre site.
Plonger plus profondément defaultdict
Jusqu'à présent, vous avez appris à utiliser le Python defaultdict
tapez en codant quelques exemples pratiques. À ce stade, vous pouvez plonger plus profondément dans implémentation de type et d'autres détails de travail. C'est ce que vous couvrirez dans les prochaines sections.
defaultdict
contre dicter
Pour que vous compreniez mieux le Python defaultdict
type, un bon exercice serait de le comparer avec sa superclasse, dicter
. Si vous voulez connaître les méthodes et les attributs spécifiques à Python defaultdict
, vous pouvez exécuter la ligne de code suivante:
>>> ensemble(dir(defaultdict)) - ensemble(dir(dicter))
'__copy__', 'default_factory', '__missing__'
Dans le code ci-dessus, vous utilisez dir ()
pour obtenir la liste des attributs valides pour dicter
et defaultdict
. Ensuite, vous utilisez un ensemble
différence pour obtenir l'ensemble des méthodes et des attributs que vous ne pouvez trouver que dans defaultdict
. Comme vous pouvez le voir, les différences entre ces deux classes sont. Vous avez deux méthodes et un attribut d'instance. Le tableau suivant montre à quoi servent les méthodes et l'attribut:
Méthode ou attribut | La description |
---|---|
.__copie__() |
Fournit un support pour copy.copy () |
.default_factory |
Contient l'appelable appelé par .__disparu__() pour fournir automatiquement des valeurs par défaut pour les clés manquantes |
.__ manquant __ (clé) |
Obtient appelé quand .__obtenir l'article__() ne trouve pas clé |
Dans le tableau ci-dessus, vous pouvez voir les méthodes et l'attribut qui font un defaultdict
différent d'un habitué dicter
. Les autres méthodes sont les mêmes dans les deux classes.
Remarque: Si vous initialisez un defaultdict
en utilisant un callable valide, vous n'obtiendrez pas KeyError
lorsque vous essayez d'accéder à une clé manquante. Toute clé qui n'existe pas obtient la valeur renvoyée par .default_factory
.
En outre, vous remarquerez peut-être qu'un defaultdict
est égal à dicter
avec les mêmes éléments:
>>> std_dict = dicter(Nombres=[[[[1, 2, 3], des lettres=[[[['une', «b», «c»])
>>> std_dict
'Nombres': [1, 2, 3], 'des lettres': ['a', 'b', 'c']
>>> def_dict = defaultdict(liste, Nombres=[[[[1, 2, 3], des lettres=[[[['une', «b», «c»])
>>> def_dict
defaultdict (, 'Nombres': [1, 2, 3], 'des lettres': ['a', 'b', 'c'])
>>> std_dict == def_dict
Vrai
Ici, vous créez un dictionnaire régulier std_dict
avec quelques éléments arbitraires. Ensuite, vous créez un defaultdict
avec les mêmes éléments. Si vous testez l’égalité de contenu des deux dictionnaires, vous verrez qu’ils sont égaux.
defaultdict.default_factory
Le premier argument du Python defaultdict
le type doit être un appelable qui ne prend aucun argument et renvoie une valeur. Cet argument est affecté à l'attribut d'instance, .default_factory
. Pour cela, vous pouvez utiliser tout appelable, y compris les fonctions, méthodes, classes, objets de type ou tout autre appelable valide. La valeur par défaut de .default_factory
est Aucun
.
Si vous instanciez defaultdict
sans passer une valeur à .default_factory
, le dictionnaire se comportera comme un habitué dicter
et l'habituel KeyError
sera levée pour les tentatives de recherche ou de modification de clés manquantes:
>>> de collections importation defaultdict
>>> dd = defaultdict()
>>> dd[[[['missing_key']
Traceback (dernier appel le plus récent):
Fichier "" , ligne 1, dans
dd[[[['missing_key']
KeyError: 'missing_key'
Ici, vous instanciez le Python defaultdict
tapez sans arguments. Dans ce cas, l'instance se comporte comme un dictionnaire standard. Donc, si vous essayez d'accéder ou de modifier une clé manquante, vous obtiendrez alors l'habituel KeyError
. À partir de ce moment, vous pouvez utiliser dd
comme un dictionnaire Python normal et, sauf si vous attribuez un nouveau callable à .default_factory
, vous ne pourrez pas utiliser la capacité de defaultdict
pour gérer automatiquement les clés manquantes.
Si vous passez Aucun
au premier argument de defaultdict
, l'instance se comportera de la même manière que vous l'avez vu dans l'exemple ci-dessus. C'est parce que .default_factory
par défaut à Aucun
, les deux initialisations sont donc équivalentes. D'un autre côté, si vous passez un objet appelable valide à .default_factory
, vous pouvez ensuite l'utiliser pour gérer les clés manquantes de manière conviviale. Voici un exemple où vous passez liste
à .default_factory
:
>>> dd = defaultdict(liste, des lettres=[[[['une', «b», «c»])
>>> dd.default_factory
>>> dd
defaultdict (, 'des lettres': ['a', 'b', 'c'])
>>> dd[[[['Nombres']
[]
>>> dd
defaultdict (, 'des lettres': ['a', 'b', 'c'], 'Nombres': [])
>>> dd[[[['Nombres'].ajouter(1)
>>> dd
defaultdict (, 'des lettres': ['a', 'b', 'c'], 'Nombres': [1])
>>> dd[[[['Nombres'] + = [[[[2, 3]
>>> dd
defaultdict (, 'des lettres': ['a', 'b', 'c'], 'Nombres': [1, 2, 3])
Dans cet exemple, vous créez un Python defaultdict
appelé dd
, alors vous utilisez liste
pour son premier argument. Le deuxième argument est appelé des lettres
et détient une liste de lettres. Tu vois ça .default_factory
détient maintenant un liste
objet qui sera appelé lorsque vous devrez fournir une valeur par défaut valeur
pour toute clé manquante.
Notez que lorsque vous essayez d'accéder à Nombres
, dd
teste si Nombres
est dans le dictionnaire. Si ce n'est pas le cas, il appelle .default_factory ()
. Puisque .default_factory
détient un liste
objet, le retourné valeur
est une liste vide ([]
).
Maintenant que dd['numbers']
est initialisé avec un vide liste
, vous pouvez utiliser .ajouter()
pour ajouter des éléments à la liste
. Vous pouvez également utiliser un opérateur d'affectation augmenté (+ =
) pour concaténer les listes [1]
et [2, 3]
. De cette façon, vous pouvez gérer les clés manquantes de manière plus Pythonic et plus efficace.
D'un autre côté, si vous passez un non appelable objet à l'initialiseur du Python defaultdict
tapez, vous obtiendrez un Erreur-type
comme dans le code suivant:
>>> defaultdict(0)
Traceback (dernier appel le plus récent):
Fichier "" , ligne 1, dans
defaultdict(0)
Erreur-type: le premier argument doit pouvoir être appelé ou Aucun
Ici, tu passes 0
à .default_factory
. Puisque 0
n'est pas un objet appelable, vous obtenez un Erreur-type
vous dire que le premier argument doit être appelable ou Aucun
. Autrement, defaultdict
ne fonctionne pas.
Garde en tête que .default_factory
est uniquement appelé depuis .__obtenir l'article__()
et pas d'autres méthodes. Cela signifie que si dd
est un defaultdict
et clé
est une clé manquante, alors dd[key]
appellera .default_factory
pour fournir une valeur par défaut valeur
, mais dd.get (clé)
revient toujours Aucun
au lieu de la valeur .default_factory
fournirait. C'est parce que .avoir()
n'appelle pas .__obtenir l'article__()
pour récupérer le clé
.
Jetez un œil au code suivant:
>>> dd = defaultdict(liste)
>>> # Appelle jj .__ getitem __ ('manquant')
>>> dd[[[['disparu']
[]
>>> # N'appelez pas dd .__ getitem __ ('another_missing')
>>> impression(dd.avoir('another_missing'))
Aucun
>>> dd
defaultdict (, 'disparu': [])
Dans ce fragment de code, vous pouvez voir que dd.get ()
Retour Aucun
plutôt que la valeur par défaut .default_factory
fournirait. C'est parce que .default_factory
est uniquement appelé depuis .__disparu__()
, qui n'est pas appelé par .avoir()
.
Notez que vous pouvez également ajouter valeurs arbitraires à un Python defaultdict
. Cela signifie que vous n'êtes pas limité aux valeurs du même type que les valeurs générées par .default_factory
. Voici un exemple:
>>> dd = defaultdict(liste)
>>> dd
defaultdict (, )
>>> dd[[[['chaîne'] = «une chaîne»
>>> dd
defaultdict (, 'chaîne': 'une chaîne')
>>> dd[[[['liste']
[]
>>> dd
defaultdict (, 'chaîne': 'une chaîne', 'liste': [])
Ici, vous créez un defaultdict
et passer dans un liste
s'opposer à .default_factory
. Cela définit vos valeurs par défaut comme des listes vides. Cependant, vous pouvez librement ajouter une nouvelle clé contenant des valeurs d'un type différent. C’est le cas avec la clé chaîne
, qui détient un str
objet au lieu d'un liste
objet.
Enfin, vous pouvez toujours changer ou mettre à jour l'appelable vous attribuez initialement à .default_factory
de la même manière que vous le feriez avec n'importe quel attribut d'instance:
>>> dd.default_factory = str
>>> dd[[[['missing_key']
''
Dans le code ci-dessus, vous modifiez .default_factory
de liste
à str
. Maintenant, chaque fois que vous essayez d'accéder à une clé manquante, votre valeur par défaut sera une chaîne vide (''
).
Selon vos cas d'utilisation pour Python defaultdict
tapez, vous devrez peut-être geler le dictionnaire une fois que vous aurez fini de le créer et de le rendre en lecture seule. Pour ce faire, vous pouvez définir .default_factory
à Aucun
après avoir rempli le dictionnaire. De cette façon, votre dictionnaire se comportera comme un standard dicter
, ce qui signifie que vous n'aurez plus de valeurs par défaut générées automatiquement.
defaultdict
contre dict.setdefault ()
Comme vous l'avez vu auparavant, dicter
fournit .définir par defaut()
, ce qui vous permettra d'attribuer des valeurs aux clés manquantes à la volée. En revanche, avec un defaultdict
vous pouvez spécifier la valeur par défaut à l'avance lorsque vous initialisez le conteneur. Vous pouvez utiliser .définir par defaut()
pour affecter les valeurs par défaut comme suit:
>>> ré = dicter()
>>> ré.définir par defaut('missing_key', [])
[]
>>> ré
'missing_key': []
Dans ce code, vous créez un dictionnaire standard, puis utilisez .définir par defaut()
pour attribuer une valeur ([]
) à la clé clé_ manquante
, qui n'était pas encore défini.
Remarque: Vous pouvez affecter n'importe quel type d'objet Python à l'aide de .définir par defaut()
. Il s'agit d'une différence importante par rapport à defaultdict
si vous considérez que defaultdict
accepte uniquement un appelable ou Aucun
.
En revanche, si vous utilisez un defaultdict
pour accomplir la même tâche, la valeur par défaut est générée à la demande chaque fois que vous essayez d'accéder ou de modifier une clé manquante. Notez qu'avec defaultdict
, la valeur par défaut est générée par l'appelable que vous transmettez en amont à l'initialiseur de la classe. Voici comment ça fonctionne:
>>> de collections importation defaultdict
>>> dd = defaultdict(liste)
>>> dd[[[['missing_key']
[]
>>> dd
defaultdict (, 'missing_key': [])
Ici, vous importez d'abord le Python defaultdict
taper de collections
. Ensuite, vous créez un defaultdict
et passer liste
à .default_factory
. Lorsque vous essayez d'accéder à une clé manquante, defaultdict
appels internes .default_factory ()
, qui contient une référence à liste
et attribue la valeur résultante (une valeur vide liste
) à clé_ manquante
.
Le code dans les deux exemples ci-dessus fait le même travail, mais le defaultdict
la version est sans doute plus lisible, conviviale, Pythonic et simple.
Remarque: Un appel à un type intégré comme liste
, ensemble
, dicter
, str
, int
, ou flotte
renverra un objet vide ou zéro pour les types numériques.
Jetez un œil aux exemples de code suivants:
>>> liste()
[]
>>> ensemble()
ensemble([])
>>> dicter()
>>> str()
''
>>> flotte()
0,0
>>> int()
0
Dans ce code, vous appelez certains types intégrés sans arguments et obtenez un objet vide ou zéro pour les types numériques.
Enfin, en utilisant un defaultdict
gérer les clés manquantes peut être plus rapide que d'utiliser dict.setdefault ()
. Jetez un œil à l'exemple suivant:
# Nom de fichier: exec_time.py
de collections importation defaultdict
de timeit importation timeit
animaux = [([([([('chat', 1), ('lapin', 2), ('chat', 3), ('chien', 4), ('dog', 1)]
std_dict = dict()
def_dict = defaultdict(list)
def group_with_dict():
pour animal, count dans animals:
std_dict.setdefault(animal, []).append(count)
revenir std_dict
def group_with_defaultdict():
pour animal, count dans animals:
def_dict[[[[animal].append(count)
revenir def_dict
impression(f'dict.setdefault() takes timeit(group_with_dict) seconds.')
impression(f'defaultdict takes timeit(group_with_defaultdict) seconds.')
If you run the script from your system’s command line, then you’ll get something like this:
$ python3 exec_time.py
dict.setdefault() takes 1.0281260240008123 seconds.
defaultdict takes 0.6704721650003194 seconds.
Here, you use timeit.timeit()
to measure the execution time of group_with_dict()
et group_with_defaultdict()
. These functions perform equivalent actions, but the first uses dict.setdefault()
, and the second uses a defaultdict
. The time measure will depend on your current hardware, but you can see here that defaultdict
is faster than dict.setdefault()
. This difference can become more important as the dataset gets larger.
Additionally, you need to consider that creating a regular dict
can be faster than creating a defaultdict
. Take a look at this code:
>>> de timeit import timeit
>>> de collections import defaultdict
>>> impression(f'dict() takes timeit(dict) seconds.')
dict() takes 0.08921320698573254 seconds.
>>> impression(f'defaultdict() takes timeit(defaultdict) seconds.')
defaultdict() takes 0.14101867799763568 seconds.
This time, you use timeit.timeit()
to measure the execution time of dict
et defaultdict
instantiation. Notice that creating a dict
takes almost half the time of creating a defaultdict
. This might not be a problem if you consider that, in real-world code, you normally instantiate defaultdict
only once.
Also notice that, by default, timeit.timeit()
will run your code a million times. That’s the reason for defining std_dict
et def_dict
out of the scope of group_with_dict()
et group_with_defaultdict()
dans exec_time.py
. Otherwise, the time measure will be affected by the instantiation time of dict
et defaultdict
.
At this point, you may have an idea of when to use a defaultdict
rather than a regular dict
. Here are three things to take into account:
-
If your code is heavily base on dictionaries and you’re dealing with missing keys all the time, then you should consider using a
defaultdict
rather than a regulardict
. -
If your dictionary items need to be initialized with a constant default value, then you should consider using a
defaultdict
instead of adict
. -
If your code relies on dictionaries for aggregating, accumulating, counting, or grouping values, and performance is a concern, then you should consider using a
defaultdict
.
You can consider the above guidelines when deciding whether to use a dict
ou un defaultdict
.
defaultdict.__missing__()
Behind the scenes, the Python defaultdict
type works by calling .default_factory
to supply default values to missing keys. The mechanism that makes this possible is .__missing__()
, a special method supported by all the standard mapping types, including dict
et defaultdict
.
Remarque: Note that .__missing__()
is automatically called by .__getitem__()
to handle missing keys and that .__getitem__()
is automatically called by Python at the same time for subscription operations like ré[key]
.
So, how does .__missing__()
work? If you set .default_factory
à Aucun
, then .__missing__()
raises a KeyError
with the key
as an argument. Autrement, .default_factory
is called without arguments to provide a default value
for the given key
. Cette value
is inserted into the dictionary and finally returned. If calling .default_factory
raises an exception, then the exception is propagated unchanged.
The following code shows a viable Python implementation for .__missing__()
:
1 def __missing__(self, key):
2 si self.default_factory est Aucun:
3 raise KeyError(key)
4 si key ne pas dans self:
5 self[[[[key] = self.default_factory()
6 revenir self[[[[key]
Here’s what this code does:
- In line 1, you define the method and its signature.
- In lines 2 and 3, you test to see if
.default_factory
estAucun
. If so, then you raise aKeyError
with thekey
as an argument. - In lines 4 and 5, you check if the
key
is not in the dictionary. If it’s not, then you call.default_factory
and assign its return value to thekey
. - In line 6, you return the
key
as expected.
Keep in mind that the presence of .__missing__()
in a mapping has no effect on the behavior of other methods that look up keys, such as .get()
ou .__contains__()
, which implements the dans
operator. C'est parce que .__missing__()
is only called by .__getitem__()
when the requested key
is not found in the dictionary. Peu importe .__missing__()
returns or raises is then returned or raised by .__getitem__()
.
Now that you’ve covered an alternative Python implementation for .__missing__()
, it would be a good exercise to try to emulate defaultdict
with some Python code. That’s what you’ll be doing in the next section.
Emulating the Python defaultdict
Type
In this section, you’ll be coding a Python class that will behave much like a defaultdict
. To do that, you’ll subclass collections.UserDict
and then add .__missing__()
. Also, you need to add an instance attribute called .default_factory
, which will hold the callable for generating default values on demand. Here’s a piece of code that emulates most of the behavior of the Python defaultdict
type:
1 import collections
2
3 class my_defaultdict(collections.UserDict):
4 def __init__(self, default_factory=Aucun, *args, **kwargs):
5 super().__init__(*args, **kwargs)
6 si ne pas callable(default_factory) et default_factory est ne pas Aucun:
sept raise TypeError('first argument must be callable or None')
8 self.default_factory = default_factory
9
dix def __missing__(self, key):
11 si self.default_factory est Aucun:
12 raise KeyError(key)
13 si key ne pas dans self:
14 self[[[[key] = self.default_factory()
15 revenir self[[[[key]
Here’s how this code works:
-
In line 1, you import
collections
to get access toUserDict
. -
In line 3, you create a class that subclasses
UserDict
. -
In line 4, you define the class initializer
.__init__()
. This method takes an argument calleddefault_factory
to hold the callable that you’ll use to generate the default values. Notice thatdefault_factory
defaults toAucun
, just like in adefaultdict
. You also need the*args
et**kwargs
for emulating the normal behavior of a regulardict
. -
In line 5, you call the superclass
.__init__()
. This means that you’re callingUserDict.__init__()
and passing*args
et**kwargs
to it. -
In line 6, you first check if
default_factory
is a valid callable object. In this case, you usecallable(object)
, which is a built-in function that returnsTrue
siobject
appears to be a callable and otherwise returnsFalse
. This check ensures that you can call.default_factory()
if you need to generate a defaultvalue
for any missingkey
. Then, you check if.default_factory
is notAucun
. -
In line 7, you raise a
TypeError
just like a regulardict
would do ifdefault_factory
estAucun
. -
In line 8, you initialize
.default_factory
. -
In line 10, you define
.__missing__()
, which is implemented as you saw before. Recall that.__missing__()
is automatically called by.__getitem__()
when a givenkey
is not in a dictionary.
If you feel in the mood to read some C code, then you can take a look at the full code for the Python defaultdict
Type in the CPython source code.
Now that you’ve finished coding this class, you can test it by putting the code into a Python script called my_dd.py
and importing it from an interactive session. Here’s an example:
>>> de my_dd import my_defaultdict
>>> dd_one = my_defaultdict(list)
>>> dd_one
>>> dd_one[[[['missing']
[]
>>> dd_one
'missing': []
>>> dd_one.default_factory = int
>>> dd_one[[[['another_missing']
0
>>> dd_one
'missing': [], 'another_missing': 0
>>> dd_two = my_defaultdict(Aucun)
>>> dd_two[[[['missing']
Traceback (most recent call last):
Fichier "" , line 1, dans
dd_two[[[['missing']
File "/home/user/my_dd.py", line 10,
in __missing__
raise KeyError(key)
KeyError: 'missing'
Here, you first import my_defaultdict
de my_dd
. Then, you create an instance of my_defaultdict
and pass list
à .default_factory
. If you try to get access to a key with a subscription operation, like dd_one['missing']
, then .__getitem__()
is automatically called by Python. If the key is not in the dictionary, then .__missing__()
is called, which generates a default value by calling .default_factory()
.
You can also change the callable assigned to .default_factory
using a normal assignment operation like in dd_one.default_factory = int
. Finally, if you pass Aucun
à .default_factory
, then you’ll get a KeyError
when trying to retrieve a missing key.
Remarque: The behavior of a defaultdict
is essentially the same as this Python equivalent. However, you’ll soon note that your Python implementation doesn’t print as a real defaultdict
but as a standard dict
. You can modify this detail by overriding .__str__()
et .__repr__()
.
You may be wondering why you subclass collections.UserDict
instead of a regular dict
pour cet exemple. The main reason for this is that subclassing built-in types can be error-prone because the C code of the built-ins doesn’t seem to consistently call special methods overridden by the user.
Here’s an example that shows some issues that you can face when subclassing dict
:
>>> class MyDict(dict):
... def __setitem__(self, key, value):
... super().__setitem__(key, Aucun)
...
>>> my_dict = MyDict(premier=1)
>>> my_dict
'first': 1
>>> my_dict[[[['second'] = 2
>>> my_dict
'first': 1, 'second': None
>>> my_dict.setdefault('third', 3)
3
>>> my_dict
'first': 1, 'second': None, 'third': 3
In this example, you create MyDict
, which is a class that subclasses dict
. Your implementation of .__setitem__()
always sets values to Aucun
. If you create an instance of MyDict
and pass a keyword argument to its initializer, then you’ll notice the class is not calling your .__setitem__()
to handle the assignment. You know that because the key premier
wasn’t assigned Aucun
.
By contrast, if you run a subscription operation like my_dict['second'] = 2
, then you’ll notice that seconde
is set to Aucun
rather than to 2
. So, this time you can say that subscription operations call your custom .__setitem__()
. Finally, notice that .setdefault()
doesn’t call .__setitem__()
either, because your troisième
key ends up with a value of 3
.
UserDict
doesn’t inherit from dict
but simulates the behavior of a standard dictionary. The class has an internal dict
instance called .data
, which is used to store the content of the dictionary. UserDict
is a more reliable class when it comes to creating custom mappings. If you use UserDict
, then you’ll be avoiding the issues you saw before. To prove this, go back to the code for my_defaultdict
and add the following method:
1 class my_defaultdict(collections.UserDict):
2 # Snip
3 def __setitem__(self, key, value):
4 impression('__setitem__() gets called')
5 super().__setitem__(key, Aucun)
Here, you add a custom .__setitem__()
that calls the superclass .__setitem__()
, which always sets the value to Aucun
. Update this code in your script my_dd.py
and import it from an interactive session as follows:
>>> de my_dd import my_defaultdict
>>> my_dict = my_defaultdict(list, premier=1)
__setitem__() gets called
>>> my_dict
'first': None
>>> my_dict[[[['second'] = 2
__setitem__() gets called
>>> my_dict
'first': None, 'second': None
In this case, when you instantiate my_defaultdict
and pass premier
to the class initializer, your custom __setitem__()
gets called. Also, when you assign a value to the key seconde
, __setitem__()
gets called as well. You now have a my_defaultdict
that consistently calls your custom special methods. Notice that all the values in the dictionary are equal to Aucun
maintenant.
Passing Arguments to .default_factory
As you saw earlier, .default_factory
must be set to a callable object that takes no argument and returns a value. This value will be used to supply a default value for any missing key in the dictionary. Even when .default_factory
shouldn’t take arguments, Python offers some tricks that you can use if you need to supply arguments to it. In this section, you’ll cover two Python tools that can serve this purpose:
lambda
functools.partial()
With these two tools, you can add extra flexibility to the Python defaultdict
type. For example, you can initialize a defaultdict
with a callable that takes an argument and, after some processing, you can update the callable with a new argument to change the default value for the keys you’ll create from this point on.
Using lambda
A flexible way to pass arguments to .default_factory
is to use lambda
. Suppose you want to create a function to generate default values in a defaultdict
. The function does some processing and returns a value, but you need to pass an argument for the function to work correctly. Here’s an example:
>>> def factory(arg):
... # Do some processing here...
... result = arg.upper()
... revenir result
...
>>> def_dict = defaultdict(lambda: factory('default value'))
>>> def_dict[[[['missing']
'DEFAULT VALUE'
In the above code, you create a function called factory()
. The function takes an argument, does some processing, and returns the final result. Then, you create a defaultdict
and use lambda
to pass the string 'default value'
à factory()
. When you try to get access to a missing key, the following steps are run:
- The dictionary
def_dict
calls its.default_factory
, which holds a reference to alambda
function. - le
lambda
function gets called and returns the value that results from callingfactory()
with'default value'
as an argument.
If you’re working with def_dict
and suddenly need to change the argument to factory()
, then you can do something like this:
>>> def_dict.default_factory = factory('another default value')
>>> def_dict[[[['another_missing']
'ANOTHER DEFAULT VALUE'
This time, factory()
takes a new string argument ('another default value'
). From now on, if you try to access or modify a missing key, then you’ll get a new default value, which is the string 'ANOTHER DEFAULT VALUE'
.
Finally, you can possibly face a situation where you need a default value that’s different from 0
ou []
. In this case, you can also use lambda
à generate a different default value. For example, suppose you have a list
of integer numbers, and you need to calculate the cumulative product of each number. Then, you can use a defaultdict
de même que lambda
comme suit:
>>> de collections import defaultdict
>>> lst = [[[[1, 1, 2, 1, 2, 2, 3, 4, 3, 3, 4, 4]
>>> def_dict = defaultdict(lambda: 1)
>>> pour nombre dans lst:
... def_dict[[[[nombre] *= nombre
...
>>> def_dict
defaultdict(<function at 0x...70>, 1: 1, 2: 8, 3: 27, 4: 64)
Here, you use lambda
to supply a default value of 1
. With this initial value, you can calculate the cumulative product of each number in lst
. Notice that you can’t get the same result using int
because the default value returned by int
is always 0
, which is not a good initial value for the multiplication operations you need to perform here.
Using functools.partial()
functools.partial(func, *args, **keywords)
is a function that returns a partial
object. When you call this object with the positional arguments (args
) and keyword arguments (keywords
), it behaves similar to when you call func(*args, **keywords)
. You can take advantage of this behavior of partial()
and use it to pass arguments to .default_factory
in a Python defaultdict
. Here’s an example:
>>> def factory(arg):
... # Do some processing here...
... result = arg.upper()
... revenir result
...
>>> de functools import partial
>>> def_dict = defaultdict(partial(factory, 'default value'))
>>> def_dict[[[['missing']
'DEFAULT VALUE'
>>> def_dict.default_factory = partial(factory, 'another default value')
>>> def_dict[[[['another_missing']
'ANOTHER DEFAULT VALUE'
Here, you create a Python defaultdict
and use partial()
to supply an argument to .default_factory
. Notice that you can also update .default_factory
to use another argument for the callable factory()
. This kind of behavior can add a lot of flexibility to your defaultdict
objects.
Conclusion
The Python defaultdict
type is a dictionary-like data structure provided by the Python standard library in a module called collections
. The class inherits from dict
, and its main added functionality is to supply default values for missing keys. In this tutorial, you’ve learned how to use the Python defaultdict
type for handling the missing keys in a dictionary.
You’re now able to:
- Create and use a Python
defaultdict
to handle missing keys - Solve real-world problems related to grouping, counting, and accumulating operations
- Know the implementation differences between
defaultdict
etdict
- Decide when and why to use a Python
defaultdict
rather than a standarddict
The Python defaultdict
type is a convenient and efficient data structure that’s designed to help you out when you’re dealing with missing keys in a dictionary. Give it a try and make your code faster, more readable, and more Pythonic!
[ad_2]