¿Cómo inicializar un dict con claves de una lista y valor vacío en Python?

251

Me gustaría obtener de esto:

keys = [1,2,3]

a esto:

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

¿Hay una manera pitónica de hacerlo?

Esta es una forma fea de hacerlo:

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

Respuestas:

390

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

En realidad, este es un método de clase, por lo que también funciona para dict-subclasses (like collections.defaultdict). El segundo argumento opcional especifica el valor a usar para las claves (por defecto es None).

Thomas Wouters
fuente
154
Tenga cuidado al inicializar en algo mutable: si llama, por ejemplo, dict.fromkeys([1, 2, 3], [])todas las teclas se asignan a la misma lista, y si modifica una, las modificará todas.
charleslparker
8
Sin {k:[] for k in [1, 2, 3]}embargo, inicializar con todavía es seguro.
Aziz Alto
263

a nadie le importaba dar una solución de comprensión 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
fuente
32
Creo que fue retrocedido a 2.7
wim
21
Esto es bueno y no sufre el problema de referencia que tiene la respuesta aceptada.
charleslparker
Esto también le permite asignar un valor predeterminado (por ejemplo False).
neverendingqs
Esta es la forma más limpia y más pitónica en Python3 IMO
Bede Constantinides
44
El uso de un dict-comp también permite que el valor sea el resultado de llamar a una función (que podría pasarse la clave como argumento, si se desea), por lo que es un mecanismo muy poderoso.
martineau
56
dict.fromkeys(keys, None)
Dominic Cooney
fuente
2
impresionante, quería listas vacías,dict.fromkeys(keys, [])
muon
12
@muon Eso ciertamente no es lo que quieres, mira el comentario de charleslparker .
gerrit
Funciona en Python versión 2.6.6.
Mike Finch
2
Cuidado: esto inicializará dict con todos los puntos clave al mismo valor único
Mendi Barel
16
>>> keyDict = {"a","b","c","d"}

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

Salida:

{'a': [], 'c': [], 'b': [], 'd': []}
Mayur Koshti
fuente
1
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Francesco Menzani
44
el nombre keyDictes engañoso, ya que la primera línea de código devuelve a set, no a dict.
Bryan Oakley
10
d = {}
for i in keys:
    d[i] = None
inspectorG4dget
fuente
1
¿Por qué Python arroja un error como TypeError: 'type' object is not iterable:?
FaCoffee
1
@FrancescoCastellani Porque listes un tipo. A menos que tenga algo así list = [], el método anterior siempre le dará el mismo error
smac89
1

En muchos flujos de trabajo en los que desea adjuntar un valor predeterminado / inicial para claves arbitrarias, no necesita hacer un hash de cada clave individualmente antes de tiempo. Puedes usar collections.defaultdict. Por ejemplo:

from collections import defaultdict

d = defaultdict(lambda: None)

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

Esto es más eficiente, ahorra tener que hacer hash todas sus claves en la instanciación. Además, defaultdictes una subclase de dict, por lo que generalmente no es necesario volver a convertir a un diccionario normal.

Para los flujos de trabajo en los que necesita controles sobre las teclas permitidas, puede usar dict.fromkeyssegún la respuesta aceptada:

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