Comment initialiser un dict avec des clés d'une liste et une valeur vide en Python?

251

J'aimerais en tirer:

keys = [1,2,3]

pour ça:

{1: None, 2: None, 3: None}

Existe-t-il une manière pythonique de le faire?

C'est une façon laide de le faire:

>>> keys = [1,2,3]
>>> dict([(1,2)])
{1: 2}
>>> dict(zip(keys, [None]*len(keys)))
{1: None, 2: None, 3: None}
Juanjo Conti
la source

Réponses:

390

dict.fromkeys([1, 2, 3, 4])

Il s'agit en fait d'une méthode de classe, donc cela fonctionne aussi pour les sous-classes dict (comme collections.defaultdict). Le deuxième argument facultatif spécifie la valeur à utiliser pour les clés (par défaut à None.)

Thomas Wouters
la source
154
Soyez prudent avec l'initialisation à quelque chose de modifiable: si vous appelez, par exemple, dict.fromkeys([1, 2, 3], [])toutes les clés sont mappées sur la même liste, et en modifier une les modifiera toutes.
charleslparker
8
L'initialisation avec {k:[] for k in [1, 2, 3]}est cependant toujours sûre.
Aziz Alto
263

personne ne se souciait de donner une solution de compréhension de dict?

>>> keys = [1,2,3,5,6,7]
>>> {key: None for key in keys}
{1: None, 2: None, 3: None, 5: None, 6: None, 7: None}
Adrien Plisson
la source
32
Je crois qu'il a été rétroporté à 2,7
wim
21
C'est bien et ne souffre pas du problème de référence que la réponse acceptée fait.
charleslparker
Cela vous permet également d'attribuer une valeur par défaut (par exemple False).
neverendingqs
C'est la manière la plus propre et la plus pythonique de Python3 IMO
Bede Constantinides
4
L'utilisation d'un dict-comp permet également à la valeur d'être le résultat de l'appel d'une fonction (qui pourrait être passée la clé comme argument, si vous le souhaitez) - tout comme un mécanisme très puissant.
martineau
56
dict.fromkeys(keys, None)
Dominic Cooney
la source
2
génial, je voulais des listes vides,dict.fromkeys(keys, [])
muon
12
@muon Ce n'est certainement pas ce que vous voulez, voir le commentaire de charleslparker .
gerrit
Fonctionne dans Python version 2.6.6.
Mike Finch
2
Attention: cela initialisera dict avec toutes les touches pointant vers la même valeur unique
Mendi Barel
16
>>> keyDict = {"a","b","c","d"}

>>> dict([(key, []) for key in keyDict])

Production:

{'a': [], 'c': [], 'b': [], 'd': []}
Mayur Koshti
la source
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Francesco Menzani
4
le nom keyDictest trompeur, car la première ligne de code renvoie un set, pas un dict.
Bryan Oakley
10
d = {}
for i in keys:
    d[i] = None
inspecteurG4dget
la source
1
Pourquoi Python envoie-t-il une erreur comme TypeError: 'type' object is not iterable:?
FaCoffee
1
@FrancescoCastellani Parce que listc'est un type. Sauf si vous avez quelque chose comme ça list = [], la méthode ci-dessus vous donnera toujours la même erreur
smac89
1

Dans de nombreux workflows où vous souhaitez attacher une valeur par défaut / initiale pour des clés arbitraires, vous n'avez pas besoin de hacher chaque clé individuellement à l'avance. Vous pouvez utiliser collections.defaultdict. Par exemple:

from collections import defaultdict

d = defaultdict(lambda: None)

print(d[1])  # None
print(d[2])  # None
print(d[3])  # None

C'est plus efficace, cela évite d'avoir à hacher toutes vos clés lors de l'instanciation. De plus, defaultdictest une sous-classe de dict, il n'est donc généralement pas nécessaire de reconvertir en dictionnaire ordinaire.

Pour les workflows où vous avez besoin de contrôles sur les touches autorisées, vous pouvez utiliser dict.fromkeysselon la réponse acceptée:

d = dict.fromkeys([1, 2, 3, 4])
jpp
la source