Sie könnten get
zweimal verwenden:
example_dict.get('key1', {}).get('key2')
Dies wird zurückgegeben, None
wenn eines vorhanden ist key1
oder key2
nicht.
Beachten Sie, dass dies immer noch ein AttributeError
if example_dict['key1']
auslösen kann, aber kein Diktat (oder ein diktatähnliches Objekt mit einer get
Methode) ist. Der try..except
Code, den Sie gepostet haben, würde TypeError
stattdessen ein if auslösenexample_dict['key1']
abonnierbar ist.
Ein weiterer Unterschied besteht darin, dass die try...except
Kurzschlüsse unmittelbar nach dem ersten fehlenden Schlüssel erfolgen. Die Anrufkette get
nicht.
Wenn Sie die Syntax beibehalten möchten, example_dict['key1']['key2']
aber nicht möchten, dass KeyErrors jemals ausgelöst wird, können Sie das Hasher-Rezept verwenden :
class Hasher(dict):
# https://stackoverflow.com/a/3405143/190597
def __missing__(self, key):
value = self[key] = type(self)()
return value
example_dict = Hasher()
print(example_dict['key1'])
# {}
print(example_dict['key1']['key2'])
# {}
print(type(example_dict['key1']['key2']))
# <class '__main__.Hasher'>
Beachten Sie, dass dies einen leeren Hasher zurückgibt, wenn ein Schlüssel fehlt.
Da Hasher
es sich um eine Unterklasse von dict
Ihnen handelt, können Sie einen Hasher genauso verwenden wie einen dict
. Es stehen dieselben Methoden und Syntax zur Verfügung. Hashers behandeln fehlende Schlüssel nur unterschiedlich.
Sie können eine reguläre dict
in eine Hasher
solche umwandeln :
hasher = Hasher(example_dict)
und konvertieren Sie ein Hasher
in ein reguläres dict
genauso einfach:
regular_dict = dict(hasher)
Eine andere Alternative besteht darin, die Hässlichkeit in einer Hilfsfunktion zu verbergen:
def safeget(dct, *keys):
for key in keys:
try:
dct = dct[key]
except KeyError:
return None
return dct
Der Rest Ihres Codes kann also relativ lesbar bleiben:
safeget(example_dict, 'key1', 'key2')