Grâce à des gens formidables sur SO, j'ai découvert les possibilités offertes par collections.defaultdict
, notamment en termes de lisibilité et de rapidité. Je les ai mis à profit avec succès.
Je voudrais maintenant implémenter trois niveaux de dictionnaires, les deux premiers étant defaultdict
et le plus bas int
. Je ne trouve pas la manière appropriée de faire cela. Voici ma tentative:
from collections import defaultdict
d = defaultdict(defaultdict)
a = [("key1", {"a1":22, "a2":33}),
("key2", {"a1":32, "a2":55}),
("key3", {"a1":43, "a2":44})]
for i in a:
d[i[0]] = i[1]
Maintenant, cela fonctionne, mais ce qui suit, qui est le comportement souhaité, ne fonctionne pas:
d["key4"]["a1"] + 1
Je soupçonne que j'aurais dû déclarer quelque part que le deuxième niveau defaultdict
est de type int
, mais je n'ai pas trouvé où ni comment le faire.
La raison pour laquelle j'utilise defaultdict
en premier lieu est d'éviter d'avoir à initialiser le dictionnaire pour chaque nouvelle clé.
Une suggestion plus élégante?
Merci pythoneers!
la source
multiprocessing
est mécontent de les envoyer dans les deux sens.d[new_key]
y accède, il appellera le lambda qui créera un nouveaudefaultdict(int)
. Et quandd[existing_key][new_key2]
on y accède, un nouveauint
sera créé.multiprocessing
et en quoi consiste une fonction nommée au niveau du module? Cette question fait suite.Une autre façon de rendre un defaultdict imbriqué pickleable consiste à utiliser un objet partiel au lieu d'un lambda:
Cela fonctionnera car la classe defaultdict est globalement accessible au niveau du module:
la source
Regardez la réponse de nosklo ici pour une solution plus générale.
Essai:
Production:
la source
Conformément à la demande de @ rschwieb pour
D['key'] += 1
, nous pouvons développer le précédent en remplaçant l'addition en définissant__add__
méthode, pour que cela se comporte plus comme uncollections.Counter()
Le premier
__missing__
sera appelé pour créer une nouvelle valeur vide, qui sera transmise__add__
. Nous testons la valeur en comptant sur des valeurs videsFalse
.Voir émulation de types numériques pour plus d'informations sur le remplacement.
Exemples:
Plutôt que de vérifier que l'argument est un nombre (très non-python, amirite!), Nous pourrions simplement fournir une valeur par défaut 0 puis tenter l'opération:
la source
Tard à la fête, mais pour une profondeur arbitraire, je me suis juste retrouvé à faire quelque chose comme ça:
L'astuce ici est essentiellement de faire de l'
DeepDict
instance elle-même une fabrique valide pour la construction des valeurs manquantes. Maintenant, nous pouvons faire des choses commela source
Aucune erreur à nouveau. Peu importe le nombre de niveaux imbriqués. pop pas d'erreur aussi
dd = DefaultDict ({"1": 333333})
la source