Dzięki wspaniałym ludziom z SO odkryłem możliwości oferowane przez collections.defaultdict
, zwłaszcza w zakresie czytelności i szybkości. Z powodzeniem je wykorzystałem.
Teraz chciałbym zaimplementować trzy poziomy słowników, z których dwa najwyższe to, defaultdict
a najniższy to int
. Nie znajduję odpowiedniego sposobu, aby to zrobić. Oto moja próba:
from collections import defaultdict
d = defaultdict(defaultdict)
a = [("key1", {"a1":22, "a2":33}),
("key2", {"a1":32, "a2":55}),
("key3", {"a1":43, "a2":44})]
for i in a:
d[i[0]] = i[1]
Teraz to działa, ale następujące, które są pożądane, nie:
d["key4"]["a1"] + 1
Podejrzewam, że powinienem był gdzieś zadeklarować, że drugi poziom defaultdict
jest typowy int
, ale nie znalazłem, gdzie ani jak to zrobić.
Powodem, dla którego używam defaultdict
w pierwszej kolejności, jest uniknięcie konieczności inicjowania słownika dla każdego nowego klucza.
Masz bardziej elegancką sugestię?
Dzięki pythoneers!
źródło
multiprocessing
jest zadowolony z wysyłania ich tam iz powrotem.d[new_key]
dostępu wywoła lambdę, która utworzy nowydefaultdict(int)
. A kiedyd[existing_key][new_key2]
zostanie uzyskany,int
zostanie utworzony nowy .multiprocessing
nazwaną funkcją na poziomie modułu? To pytanie idzie dalej.Innym sposobem na utworzenie zagnieżdżonego, dającego się trawić defaultdict jest użycie częściowego obiektu zamiast lambda:
To zadziała, ponieważ klasa defaultdict jest globalnie dostępna na poziomie modułu:
źródło
Spójrz na odpowiedź nosklo jest tutaj bardziej ogólnego rozwiązania.
Testowanie:
Wynik:
źródło
Zgodnie z żądaniem @ rschwieb
D['key'] += 1
, możemy rozszerzyć poprzednie , nadpisując dodawanie przez zdefiniowanie__add__
metody, aby zachowywała się bardziej jakcollections.Counter()
Pierwsza
__missing__
zostanie wywołana w celu utworzenia nowej pustej wartości, która zostanie przekazana do__add__
. Testujemy wartość, licząc na puste wartościFalse
.Aby uzyskać więcej informacji na temat zastępowania, zobacz emulowanie typów liczbowych .
Przykłady:
Zamiast sprawdzać argument jest liczbą (bardzo nie-Pythona, amirite!), Możemy po prostu podać domyślną wartość 0, a następnie spróbować wykonać operację:
źródło
Spóźniony na imprezę, ale dla dowolnej głębi po prostu stwierdziłem, że robię coś takiego:
Trik polega na tym, aby
DeepDict
sama instancja była prawidłową fabryką do konstruowania brakujących wartości. Teraz możemy robić takie rzeczy jakźródło
Znowu żadnych błędów. Bez względu na to, ile poziomów jest zagnieżdżonych. pop też nie ma błędu
dd = DefaultDict ({"1": 333333})
źródło