2012-07-16 29 views
59

Mi intento de crear un diccionario de listas mediante programación no me permite abordar las claves del diccionario de forma individual. Cada vez que creo el diccionario de listas y trato de anexar a una clave, todas se actualizan. He aquí un caso de prueba muy simple:¿Cómo inicializo un diccionario de listas vacías en Python?

data = {} 
data = data.fromkeys(range(2),[]) 
data[1].append('hello') 
print data 

Resultado real: {0: ['hello'], 1: ['hello']}

Resultado esperado: {0: [], 1: ['hello']}

aquí es lo que funciona

data = {0:[],1:[]} 
data[1].append('hello') 
print data 

real y el resultado previsto: {0: [], 1: ['hello']}

Por qué ¿el método fromkeys no funciona como se esperaba?

Respuesta

70

Pasando [] como segundo argumento a dict.fromkeys() da un resultado bastante inútil - todos los valores en el diccionario será la lista de objetos misma.

En Python 2.7 o superior, se puede utilizar una comprensión dicitonary lugar:

data = {k: [] for k in range(2)} 

En versiones anteriores de Python, puede utilizar

data = dict((k, []) for k in range(2)) 
+1

Bueno, este es un comportamiento poco intuitivo, ¿alguna idea sobre por qué se usa el mismo objeto para todas las teclas? – Bar

+2

@Bar Porque no hay nada más que la función pueda hacer dentro de la semántica del lenguaje Python. Usted transfiere un solo objeto para usarlo como valor para todas las claves, de modo que ese único objeto se use para todas las claves.Sería mejor para el método 'fromkeys()' aceptar una función de fábrica en su lugar, así podríamos pasar 'list' como una función, y ese funciton sería llamado una vez por cada clave creada, pero esa no es la API real de 'dict.fromkeys()'. –

42

Uso defaultdict lugar:

from collections import defaultdict 
data = defaultdict(list) 
data[1].append('hello') 

De esta manera usted no tiene que inicializar todas las teclas que desea utilizar para las listas de antemano.

Lo que está sucediendo en su ejemplo es que utiliza una lista (mutable):

alist = [1] 
data = dict.fromkeys(range(2), alist) 
alist.append(2) 
print data 

emitiría {0: [1, 2], 1: [1, 2]}.

+2

En mi caso, necesito inicializar todas las claves de antemano para que el resto de la lógica del programa pueda funcionar como se esperaba, pero esto sería una buena solución de lo contrario. Gracias. –

6

Usted está llenando sus diccionarios con referencias a una sola lista, por lo que cuando la actualice, la actualización se reflejará en todas las referencias. Pruebe una comprensión de diccionario en su lugar. Ver Create a dictionary with list comprehension in Python

d = {k : v for k in blah blah blah} 
+0

gran sugerencia sobre la inicialización de los valores del diccionario ... gracias cobie! Extendí tu ejemplo para restablecer los valores en un diccionario existente, d. Lo realicé de la siguiente manera: d = {k: 0 para k en d} – John

-3

Usted podría utilizar esto:

data[:1] = ['hello'] 
+2

Podría ser útil para el OP explicar * por qué * esto funciona. La pregunta original publicada explica por qué no funciona como se esperaba. –

+0

@ william.taylor.09 es un poco obvio por qué esto funciona, ¿no? –

+0

OP pregunta si "¿Por qué el método de las teclas de función no funciona como se esperaba?" –

Cuestiones relacionadas