Mam zagnieżdżony słownik. Czy jest tylko jeden sposób, aby bezpiecznie uzyskać wartości?
try:
example_dict['key1']['key2']
except KeyError:
pass
A może Python ma metodę podobną get()
do zagnieżdżonego słownika?
python
dictionary
methods
except
Arti
źródło
źródło
except keyerror:
klauzuli zawsze można określić wartość domyślną .Odpowiedzi:
Możesz użyć
get
dwa razy:Zwróci to,
None
jeśli albo nie istnieje,key1
albokey2
nie.Zauważ, że może to nadal wywołać
AttributeError
ifexample_dict['key1']
istnieje, ale nie jest dict (lub obiektem podobnym do dyktu zget
metodą).try..except
Kod, który pisał by podnieśćTypeError
zamiast jeśliexample_dict['key1']
jest unsubscriptable.Inną różnicą jest to, że
try...except
zwarcia natychmiast po pierwszym brakującym kluczu. Łańcuchget
połączeń nie.Jeśli chcesz zachować składnię,
example_dict['key1']['key2']
ale nie chcesz, aby kiedykolwiek generowała błędy KeyErrors, możesz użyć przepisu Hasher :Zwróć uwagę, że zwraca to pusty hasher, gdy brakuje klucza.
Ponieważ
Hasher
jest to podklasadict
, możesz używać Hashera w taki sam sposób, w jaki możesz użyćdict
. Wszystkie te same metody i składnia są dostępne, Hashery po prostu traktują brakujące klucze inaczej.Możesz przekształcić zwykły
dict
wHasher
taki:i równie łatwo przekonwertuj a
Hasher
na zwykłydict
:Inną alternatywą jest ukrycie brzydoty w funkcji pomocniczej:
Więc reszta twojego kodu może pozostać stosunkowo czytelna:
źródło
safeget
metoda jest pod wieloma względami niezbyt bezpieczna, ponieważ zastępuje oryginalny słownik, co oznacza, że nie można bezpiecznie wykonywać takich rzeczy jaksafeget(dct, 'a', 'b') or safeget(dct, 'a')
.dct = dct[key]
ponownie przypisuje nową wartość do zmiennej lokalnejdct
. Nie powoduje to mutacji oryginalnego dyktowania (więc oryginalny dykt pozostaje nienaruszonysafeget
). Gdyby, z drugiej strony,dct[key] = ...
został użyty, oryginalny dykt zostałby zmodyfikowany. Innymi słowy, w Pythonie nazwy są powiązane z wartościami . Przypisanie nowej wartości do nazwy nie wpływa na starą wartość (chyba że nie ma już odniesień do starej wartości, w którym to przypadku (w CPythonie) zostanie zebrana śmieci.)safeget
Metoda nie powiedzie się także w przypadku, gdy klucz zagnieżdżonych dict istnieje, ale wartość jest null. RzuciTypeError: 'NoneType' object is not subscriptable
kolejną iteracjęMożesz także użyć Pythona Redukcja :
źródło
Łącząc wszystkie te odpowiedzi tutaj i małe zmiany, które wprowadziłem, myślę, że ta funkcja byłaby przydatna. jest bezpieczny, szybki i łatwy w utrzymaniu.
Przykład:
źródło
deep_get({'a': 1}, "a.b")
daje,None
ale spodziewałbym się wyjątkuKeyError
lub czegoś innego.None
naRaise KeyError
Opierając się na odpowiedzi Yoav, jeszcze bezpieczniejsze podejście:
źródło
Rozwiązanie rekurencyjne. To nie jest najbardziej wydajne, ale uważam, że jest nieco bardziej czytelne niż inne przykłady i nie opiera się na functools.
Przykład
Bardziej dopracowana wersja
źródło
Chociaż podejście redukujące jest zgrabne i krótkie, myślę, że prostą pętlę łatwiej jest opanować. Dołączyłem również domyślny parametr.
Aby zrozumieć, jak działa redukcja jednowarstwowa, wykonałem następujące czynności. Ale ostatecznie podejście pętlowe wydaje mi się bardziej intuicyjne.
Stosowanie
źródło
Proponuję spróbować
python-benedict
.Jest to
dict
podklasa, która zapewnia obsługę ścieżki klucza i wiele więcej.Instalacja:
pip install python-benedict
teraz możesz uzyskać dostęp do zagnieżdżonych wartości za pomocą keypath :
lub uzyskaj dostęp do zagnieżdżonych wartości za pomocą listy kluczy :
Jest dobrze przetestowany i open-source na GitHub :
https://github.com/fabiocaccamo/python-benedict
źródło
d.get('a.b[0].c[-1]')
Prosta klasa, która może zawijać dyktando i pobierać na podstawie klucza:
Na przykład:
Jeśli klucz nie istnieje,
None
domyślnie zwraca . Możesz to zmienić za pomocądefault=
klucza wFindDict
opakowaniu - na przykład:źródło
aby odzyskać klucz drugiego poziomu, możesz to zrobić:
źródło
Po zapoznaniu się z tym, aby uzyskać szczegółowe informacje o atrybutach, wykonałem następujące czynności, aby bezpiecznie uzyskać zagnieżdżone
dict
wartości za pomocą notacji kropkowej. To działa dla mnie, ponieważ mojedicts
są zdeserializowane obiekty MongoDB, więc wiem, że nazwy kluczy nie zawierają.
s. Ponadto w moim kontekście mogę określić fałszywą wartość rezerwową (None
), której nie mam w moich danych, dzięki czemu mogę uniknąć wzorca try / except podczas wywoływania funkcji.źródło
fallback
nie jest faktycznie używany w funkcji..
sep=','
słowo kluczowe arg, aby uogólnić dla podanych (sep, fallback) warunków. A @denvar, jeśliobj
powiedziano, że typint
po sekwencji redukcji, to obj [nazwa] wywołuje błąd TypeError, który łapię. Gdybym zamiast tego użył obj.get (name) lub obj.get (name, fallback), podniósłby AttributeError, więc tak czy inaczej musiałbym złapać.Jeszcze inna funkcja dla tej samej rzeczy również zwraca wartość logiczną, która wskazuje, czy klucz został znaleziony, czy nie, i obsługuje nieoczekiwane błędy.
przykład użycia:
źródło
Możesz użyć pydash:
https://pydash.readthedocs.io/en/latest/api.html
źródło
Adaptacja odpowiedzi unutbu, która okazała się przydatna w moim własnym kodzie:
Generuje wpis słownikowy dla key1, jeśli nie ma już tego klucza, aby uniknąć błędu KeyError. Jeśli chcesz skończyć ze słownikiem zagnieżdżonym, który i tak zawiera parowanie kluczy, tak jak ja, wydaje się to najłatwiejszym rozwiązaniem.
źródło
Ponieważ zgłoszenie błędu klucza, jeśli brakuje jednego z kluczy, jest rozsądną rzeczą do zrobienia, nie możemy go nawet sprawdzić i uzyskać tak pojedynczego:
źródło
Niewielka poprawa w
reduce
podejściu do listy. Używa również ścieżki danych jako ciągu podzielonego kropkami zamiast tablicy.źródło
Rozwiązanie, którego użyłem, jest podobne do double get, ale z dodatkową możliwością uniknięcia błędu TypeError przy użyciu logiki if else:
Jednak im bardziej zagnieżdżony jest słownik, tym bardziej staje się to nieporęczne.
źródło
W przypadku zagnieżdżonych wyszukiwań w słowniku / JSON można użyć dyktatora
pip install dictor
obiekt dyktowania
aby otrzymać elementy Lonestar, wystarczy podać ścieżkę oddzieloną kropkami, tj
możesz podać wartość rezerwową w przypadku, gdy klucz nie znajduje się w ścieżce
jest mnóstwo innych opcji, które możesz zrobić, takich jak ignorowanie wielkości liter i używanie innych znaków oprócz „”. jako separator ścieżki,
https://github.com/perfecto25/dictor
źródło
Niewiele zmieniłem tę odpowiedź. Dodałem sprawdzenie, czy używamy listy z numerami. Więc teraz możemy go używać w dowolny sposób.
deep_get(allTemp, [0], {})
lubdeep_get(getMinimalTemp, [0, minimalTemperatureKey], 26)
itpźródło
Jest już wiele dobrych odpowiedzi, ale wymyśliłem funkcję o nazwie get podobną do lodash get w JavaScript land, która obsługuje również sięganie do list według indeksu:
źródło