2013-03-20 15 views
27

To było przyczyną mi trochę żal ...dict.fromkeys wszystkich punktów na tej samej liście

I stworzył słownik z listy

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

d['a'] is d['b'] # returns True 

Jak mogę zrobić każdą wartość słownika A oddzielna lista? Czy jest to możliwe bez powtarzania wszystkich kluczy i ustawiania ich na równi z listą? Chciałbym zmodyfikować jedną listę bez zmiany wszystkich pozostałych.

Odpowiedz

25

Można użyć zrozumieniem dict:

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

'lista (wartość)' to to samo, co "wartość [:]" tutaj? – Droogans

+1

@Droogany: Tak. Po prostu uważam, że pusta notacja plastyczna jest brzydka. – Blender

6

Można to wykorzystać:

l = ['a', 'b', 'c'] 
d = dict((k, [0, 0]) for k in l) 
2
l = ['a','b','c'] 
d = dict((i, [0, 0]) for i in l) 
-4
keys = ['a','b','c'] 
value = [0, 0] 
d = dict.fromkeys(keys,value) 
print d 
# {'a':[0, 0], 'b':[0, 0], 'c':[0, 0]} 
+0

Witamy w Stack Overflow! Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, dlaczego i/lub sposób, w jaki odpowie na to pytanie, znacznie poprawiłoby jego długoterminową wartość. Proszę [edytuj] swoją odpowiedź, aby dodać wyjaśnienie. – CodeMouse92

+0

Ta odpowiedź nie działa. Spróbuj 'd ['a'] to d ['b']', a zobaczysz, że nadal jest "True", co oznacza, że ​​wszystkie wskazują na tę samą tablicę. Pozostałe odpowiedzi są poprawne, ponieważ każdy klucz ma odrębną kopię tablicy –

4

Ta odpowiedź jest tutaj, aby wyjaśnić to zachowanie nikomu flummoxed wynikami próbują utworzyć instancję dict z fromkeys() z domyślną wartością zmienną w tym dict.

Rozważmy:

#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 

więc każda zmiana l1 nie wpłynie l2 i vice versa. Dotyczy to wszystkich możliwych zmian, w tym dict.

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

może to być przydatna funkcja. tutaj przypisujemy każdemu kluczowi wartość domyślną, która również jest pustą listą.

# 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 

Rzeczywiście wszystkie używają tego samego ref. Zmiana na jedną jest zmianą dla wszystkich, ponieważ w rzeczywistości są one tym samym obiektem!

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

dla wielu, to nie było to, co było zamierzone!

Spróbujmy teraz, używając jawnej kopii listy jako wartości domyślnej.

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

i teraz utwórz dyktor z kopią 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']} 

Nadal nie ma radości! Słyszę, że ktoś krzyczy, bo użyłem pustej listy!

>>> 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']} 

Domyślne zachowanie fromkeys() jest przypisanie None wartości.

>>> 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 

Rzeczywiście, wszystkie wartości są takie same (i jedyne!) None. Teraz, iterujemy, na jeden z niezliczonych sposobów, poprzez dict i zmieniamy wartość.

>>> for k, _ in dict4.items(): 
... dict4[k] = [] 

>>> dict4 
{'c': [], 'b': [], 'a': []} 

Hmm. Wygląda tak samo jak wcześniej!

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

Jednak są one rzeczywiście różne [] s, co w tym przypadku było zamierzonym rezultatem.

+0

Musimy więc powtórzyć? – user1712447

Powiązane problemy