Tengo un diccionario anidado. ¿Hay una sola forma de obtener valores de forma segura?
try:
example_dict['key1']['key2']
except KeyError:
pass
¿O tal vez Python tiene un método como get()para diccionario anidado?
python
dictionary
methods
except
Arti
fuente
fuente

except keyerror:cláusula.Respuestas:
Puedes usar
getdos veces:Esto volverá
Nonesi existekey1okey2no existe.Tenga en cuenta que esto aún podría generar un
AttributeErrorifexample_dict['key1'], pero no es un dict (o un objeto similar a un dict con ungetmétodo). Eltry..exceptcódigo que publicó generaría unTypeErrorlugar si noexample_dict['key1']se puede suscribir.Otra diferencia es que los
try...exceptcortocircuitos inmediatamente después de la primera clave faltante. La cadena degetllamadas no.Si desea preservar la sintaxis,
example_dict['key1']['key2']pero no desea que aumente nunca KeyErrors, puede usar la receta Hasher :Tenga en cuenta que esto devuelve un Hasher vacío cuando falta una clave.
Dado que
Hasheres una subclase dedictusted, puede usar un Hasher de la misma manera que podría usar undict. Todos los mismos métodos y sintaxis están disponibles, Hashers solo trata las claves faltantes de manera diferente.Puede convertir una regular
dicten unaHashercomo esta:y convierta a
Hashera regular con ladictmisma facilidad:Otra alternativa es ocultar la fealdad en una función auxiliar:
Entonces, el resto de su código puede permanecer relativamente legible:
fuente
safegetmuchos sentidos, el método no es muy seguro, ya que sobrescribe el diccionario original, lo que significa que no puede hacer cosas con seguridadsafeget(dct, 'a', 'b') or safeget(dct, 'a').safegetnunca sobrescribe el diccionario original. Devolverá el diccionario original, un valor del diccionario original oNone.dct = dct[key]reasigna un nuevo valor a la variable localdct. Esto no muta el dict original (por lo que el dict original no se ve afectado porsafeget). Si, por otro lado, sedct[key] = ...hubiera utilizado, entonces el dict original se habría modificado. En otras palabras, en Python los nombres están vinculados a valores . Asignación de un nuevo valor a un nombre no afecta el valor de edad (a menos que ya no hay más referencias al antiguo valor, en cuyo caso (en CPython) que conseguirá basura recogida.)También podría usar python reduce :
fuente
Al combinar todas estas respuestas aquí y los pequeños cambios que hice, creo que esta función sería útil. Es seguro, rápido y fácil de mantener.
Ejemplo:
fuente
deep_get({'a': 1}, "a.b")daNonepero esperaría una excepción comoKeyErroro algo más.NoneaRaise KeyErrorA partir de la respuesta de Yoav, un enfoque aún más seguro:
fuente
Una solución recursiva. No es el más eficiente, pero me parece un poco más legible que los otros ejemplos y no se basa en functools.
Ejemplo
Una versión más pulida.
fuente
Si bien el enfoque de reducción es ordenado y breve, creo que un bucle simple es más fácil de asimilar. También he incluido un parámetro predeterminado.
Como ejercicio para comprender cómo funcionaba la reducción de una línea, hice lo siguiente. Pero en última instancia, el enfoque de bucle me parece más intuitivo.
Uso
fuente
Te sugiero que pruebes
python-benedict.Es un
dictsubclase que proporciona soporte de keypath y mucho más.Instalación:
pip install python-benedictahora puede acceder a valores anidados utilizando keypath :
o acceder a valores anidados utilizando la lista de claves :
Está bien probado y de código abierto en GitHub :
https://github.com/fabiocaccamo/python-benedict
fuente
d.get('a.b[0].c[-1]')Una clase simple que puede ajustar un dict y recuperar en función de una clave:
Por ejemplo:
Si la clave no existe, regresa
Nonepor defecto. Puede anular eso usando unadefault=clave en elFindDictcontenedor, por ejemplo`:fuente
para una recuperación de clave de segundo nivel, puede hacer esto:
fuente
Después de ver esto para obtener atributos profundos, hice lo siguiente para obtener
dictvalores anidados de manera segura usando la notación de puntos. Esto funciona para mí porquedictsson objetos MongoDB deserializados, así que sé que los nombres de las claves no contienen.s. Además, en mi contexto, puedo especificar un valor de respaldo falso (None) que no tengo en mis datos, por lo que puedo evitar el patrón try / except al llamar a la función.fuente
fallbacken realidad no se usa en la función..sep=','palabra clave arg para generalizar para determinadas condiciones (sep, fallback). Y @denvar, siobjse dice de tipointdespués de una secuencia de reducción, entonces obj [nombre] genera un TypeError, que atrapo. Si usé obj.get (name) u obj.get (name, fallback) en su lugar, generaría un AttributeError, por lo que de cualquier manera tendría que atraparlo.Otra función para la misma cosa, también devuelve un valor booleano para representar si se encontró la clave o no y maneja algunos errores inesperados.
ejemplo de uso:
fuente
Puedes usar pydash:
https://pydash.readthedocs.io/en/latest/api.html
fuente
Una adaptación de la respuesta de unutbu que encontré útil en mi propio código:
Genera una entrada de diccionario para la clave1 si aún no tiene esa clave para evitar KeyError. Si quieres terminar un diccionario anidado que incluye ese emparejamiento de teclas de todos modos como lo hice yo, esta parece ser la solución más fácil.
fuente
Dado que es razonable hacer un error de clave si falta una de las claves, incluso no podemos verificarlo y obtenerlo de la siguiente manera:
fuente
Poca mejora en el
reduceenfoque para que funcione con la lista. También se utiliza la ruta de datos como cadena dividida por puntos en lugar de matriz.fuente
Una solución que he usado que es similar al doble get pero con la capacidad adicional de evitar un TypeError usando la lógica if else:
Sin embargo, cuanto más anidado está el diccionario, más engorroso se vuelve.
fuente
Para búsquedas anidadas de diccionario / JSON, puede usar dictor
pip install dictor
objeto dict
para obtener los elementos de Lonestar, simplemente proporcione una ruta separada por puntos, es decir
puede proporcionar un valor de reserva en caso de que la clave no esté en la ruta
Hay muchas más opciones que puedes hacer, como ignorar el uso de mayúsculas y minúsculas y usar otros caracteres además de '.' como un separador de ruta,
https://github.com/perfecto25/dictor
fuente
Cambié poco esta respuesta. Agregué verificar si estamos usando la lista con números. Así que ahora podemos usarlo de cualquier manera.
deep_get(allTemp, [0], {})odeep_get(getMinimalTemp, [0, minimalTemperatureKey], 26)etc.fuente
Ya hay muchas buenas respuestas, pero se me ocurrió una función llamada get similar to lodash get en JavaScript land que también permite acceder a las listas por índice:
fuente