method functions dictionaries dict python

python - functions - dict.fromkeys apuntan a la misma lista



dictionary method python (4)

Esto me estaba causando un poco de dolor ...

Creé un diccionario de una lista

l = [''a'',''b'',''c''] d = dict.fromkeys(l, [0,0]) # initializing dictionary with [0,0] as values d[''a''] is d[''b''] # returns True

¿Cómo puedo hacer que cada valor del diccionario sea una lista separada? ¿Es esto posible sin iterar sobre todas las teclas y establecerlas igual a una lista? Me gustaría modificar una lista sin cambiar todas las demás.


Esta respuesta está aquí para explicar este comportamiento a cualquier persona desconcertada por los resultados que obtienen de intentar crear una instancia de un dict con fromkeys() con un valor predeterminado mutable en ese dict .

Considerar:

#Python 3.4.3 (default, Nov 17 2016, 01:08:31) # start by validating that different variables pointing to an # empty mutable are indeed different references. >>> l1 = [] >>> l2 = [] >>> id(l1) 140150323815176 >>> id(l2) 140150324024968

entonces cualquier cambio a l1 no afectará a l2 y viceversa. esto sería cierto para cualquier mutable hasta el momento, incluida una dict .

# create a new dict from an iterable of keys >>> dict1 = dict.fromkeys([''a'', ''b'', ''c''], []) >>> dict1 {''c'': [], ''b'': [], ''a'': []}

esto puede ser una función útil. aquí estamos asignando a cada tecla un valor predeterminado que también resulta ser una lista vacía.

# the dict has its own id. >>> id(dict1) 140150327601160 # but look at the ids of the values. >>> id(dict1[''a'']) 140150323816328 >>> id(dict1[''b'']) 140150323816328 >>> id(dict1[''c'']) 140150323816328

De hecho, todos usan la misma referencia. ¡Un cambio a uno es un cambio para todos, ya que de hecho son el mismo objeto!

>>> dict1[''a''].append(''apples'') >>> dict1 {''c'': [''apples''], ''b'': [''apples''], ''a'': [''apples'']} >>> id(dict1[''a'']) >>> 140150323816328 >>> id(dict1[''b'']) 140150323816328 >>> id(dict1[''c'']) 140150323816328

para muchos, ¡esto no era lo que se pretendía!

Ahora intentémoslo haciendo una copia explícita de la lista que se usa como el valor predeterminado.

>>> empty_list = [] >>> id(empty_list) 140150324169864

y ahora crea un dict con una copia de empty_list .

>>> dict2 = dict.fromkeys([''a'', ''b'', ''c''], empty_list[:]) >>> id(dict2) 140150323831432 >>> id(dict2[''a'']) 140150327184328 >>> id(dict2[''b'']) 140150327184328 >>> id(dict2[''c'']) 140150327184328 >>> dict2[''a''].append(''apples'') >>> dict2 {''c'': [''apples''], ''b'': [''apples''], ''a'': [''apples'']}

Todavía no hay alegría! Escuché a alguien gritar, ¡es porque utilicé una lista vacía!

>>> not_empty_list = [0] >>> dict3 = dict.fromkeys([''a'', ''b'', ''c''], not_empty_list[:]) >>> dict3 {''c'': [0], ''b'': [0], ''a'': [0]} >>> dict3[''a''].append(''apples'') >>> dict3 {''c'': [0, ''apples''], ''b'': [0, ''apples''], ''a'': [0, ''apples'']}

El comportamiento predeterminado de fromkeys() es asignar None al valor.

>>> dict4 = dict.fromkeys([''a'', ''b'', ''c'']) >>> dict4 {''c'': None, ''b'': None, ''a'': None} >>> id(dict4[''a'']) 9901984 >>> id(dict4[''b'']) 9901984 >>> id(dict4[''c'']) 9901984

De hecho, todos los valores son los mismos (¡y el único!) None . Ahora, iteremos, en una de una miríada de formas, a través del dict y cambiemos el valor.

>>> for k, _ in dict4.items(): ... dict4[k] = [] >>> dict4 {''c'': [], ''b'': [], ''a'': []}

Hmm. ¡Parece lo mismo que antes!

>>> id(dict4[''a'']) 140150318876488 >>> id(dict4[''b'']) 140150324122824 >>> id(dict4[''c'']) 140150294277576 >>> dict4[''a''].append(''apples'') >>> dict4 >>> {''c'': [], ''b'': [], ''a'': [''apples'']}

Pero en realidad son diferentes [] s, que en este caso fue el resultado esperado.


Puedes usar esto:

l = [''a'', ''b'', ''c''] d = dict((k, [0, 0]) for k in l)


Puedes usar una comprensión dict:

>>> keys = [''a'',''b'',''c''] >>> value = [0, 0] >>> {key: list(value) for key in keys} {''a'': [0, 0], ''b'': [0, 0], ''c'': [0, 0]}


l = [''a'',''b'',''c''] d = dict((i, [0, 0]) for i in l)