2012-07-16 17 views
59

Moja próba programowego utworzenia słownika list nie pozwala mi indywidualnie adresować kluczy słownika. Ilekroć tworzę słownik list i próbuję dołączyć do jednego klucza, wszystkie są aktualizowane. Oto bardzo prosty przypadek testowy:Jak zainicjować słownik pustych list w Pythonie?

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

Rzeczywisty rezultat: {0: ['hello'], 1: ['hello']}

Oczekiwany wynik: {0: [], 1: ['hello']}

Oto, co działa

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

faktycznych i oczekiwany wynik: {0: [], 1: ['hello']}

Czemu czy metoda fromkeys nie działa zgodnie z oczekiwaniami?

Odpowiedz

70

Przechodząc [] jako drugi argument do dict.fromkeys() daje wynik raczej bezużyteczny - wszystkie wartości w słowniku będzie lista obiektów samo.

W Pythonie 2.7 lub wyżej, można użyć dicitonary zrozumieniem Zamiast:

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

we wcześniejszych wersjach Pythona, można użyć

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

Cóż to jest raczej nieintuicyjne zachowanie, jakikolwiek pomysł na to, dlaczego ten sam obiekt jest używany do wszystkich kluczy? – Bar

+2

@Bar Ponieważ nie ma nic więcej, funkcja mogłaby zrobić w ramach semantyki języka Python. Przekazujesz pojedynczy obiekt, który ma być użyty jako wartość dla wszystkich kluczy, tak aby pojedynczy obiekt był używany dla wszystkich kluczy.Byłoby lepiej, aby metoda 'fromkeys()' przyjmowała funkcję fabryczną, więc moglibyśmy przekazać funkcję 'list' jako funkcję, i ta funkcja byłaby wywoływana raz dla każdego utworzonego klucza, ale to nie jest rzeczywiste API 'dict.fromkeys()'. –

42

Zastosowanie defaultdict zamiast:

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

W ten sposób nie musisz zainicjować wszystkie klucze, które chcesz użyć do list wcześniej.

Co się dzieje w Twojej przykładzie jest to, że używasz jeden (zmienny) listę:

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

zwróci wynik {0: [1, 2], 1: [1, 2]}.

+2

W moim przypadku muszę wcześniej zainicjować wszystkie klucze, aby reszta logiki programu działała zgodnie z oczekiwaniami, ale byłaby to dobre rozwiązanie w przeciwnym razie. Dzięki. –

6

Zapełniasz swoje słowniki odniesieniami do pojedynczej listy, więc po aktualizacji aktualizacja jest odzwierciedlana we wszystkich odniesieniach. Zamiast tego spróbuj zrozumieć słownik. Zobacz Create a dictionary with list comprehension in Python

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

świetna sugestia na temat inicjowania wartości słownika ... dzięki cobie! Rozszerzyłem Twój przykład, aby zresetować wartości w istniejącym słowniku, d. Wykonałem to w następujący sposób: d = {k: 0 dla k in d} – John

-3

Można użyć tego:

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

Pomocne może być dla OP wyjaśnienie * dlaczego * to działa. Oryginalne pytanie zadało pytanie, dlaczego nie działa zgodnie z oczekiwaniami. –

+0

@ william.taylor.09 to dość oczywiste, dlaczego to działa, prawda? –

+0

OP jest (był) z pytaniem "Dlaczego metoda Fromkeys nie działa zgodnie z oczekiwaniami?" –

Powiązane problemy