Puedes usar getdos veces:
example_dict.get('key1', {}).get('key2')
Esto volverá Nonesi existe key1o key2no existe.
Tenga en cuenta que esto aún podría generar un AttributeErrorif example_dict['key1'], pero no es un dict (o un objeto similar a un dict con un getmétodo). El try..exceptcódigo que publicó generaría un TypeErrorlugar si no example_dict['key1']se puede suscribir.
Otra diferencia es que los try...exceptcortocircuitos inmediatamente después de la primera clave faltante. La cadena de getllamadas no.
Si desea preservar la sintaxis, example_dict['key1']['key2']pero no desea que aumente nunca KeyErrors, puede usar la receta Hasher :
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'>
Tenga en cuenta que esto devuelve un Hasher vacío cuando falta una clave.
Dado que Hasheres una subclase de dictusted, puede usar un Hasher de la misma manera que podría usar un dict. Todos los mismos métodos y sintaxis están disponibles, Hashers solo trata las claves faltantes de manera diferente.
Puede convertir una regular dicten una Hashercomo esta:
hasher = Hasher(example_dict)
y convierta a Hashera regular con la dictmisma facilidad:
regular_dict = dict(hasher)
Otra alternativa es ocultar la fealdad en una función auxiliar:
def safeget(dct, *keys):
for key in keys:
try:
dct = dct[key]
except KeyError:
return None
return dct
Entonces, el resto de su código puede permanecer relativamente legible:
safeget(example_dict, 'key1', 'key2')