Gracias a algunas personas excelentes en SO, descubrí las posibilidades que ofrece collections.defaultdict
, especialmente en legibilidad y velocidad. Los he puesto en uso con éxito.
Ahora me gustaría implementar tres niveles de diccionarios, siendo los dos superiores defaultdict
y el más bajo int
. No encuentro la forma adecuada de hacer esto. Aquí está mi intento:
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]
Ahora esto funciona, pero lo siguiente, que es el comportamiento deseado, no funciona:
d["key4"]["a1"] + 1
Sospecho que debería haber declarado en alguna parte que el segundo nivel defaultdict
es de tipo int
, pero no encontré dónde ni cómo hacerlo.
La razón que estoy usando defaultdict
en primer lugar es para evitar tener que inicializar el diccionario para cada nueva clave.
¿Alguna sugerencia más elegante?
Gracias pitoneros!
fuente
multiprocessing
está contento con enviarlos de un lado a otro.d[new_key]
se accede, llamará a la lambda que creará una nuevadefaultdict(int)
. Y cuandod[existing_key][new_key2]
se accede, seint
creará una nueva .multiprocessing
y qué es una función de nivel de módulo con nombre? Esta pregunta sigue.Otra forma de hacer un veredicto predeterminado anidado y encurtido es usar un objeto parcial en lugar de una lambda:
Esto funcionará porque la clase defaultdict es accesible globalmente a nivel de módulo:
fuente
Mira la respuesta de nosklo aquí para una solución más general.
Pruebas:
Salida:
fuente
De acuerdo con la solicitud de @ rschwieb para
D['key'] += 1
, podemos ampliar la anterior anulando la suma definiendo el__add__
método, para que esto se comporte más como uncollections.Counter()
Primero
__missing__
se llamará para crear un nuevo valor vacío, que se pasará a__add__
. Probamos el valor, contando con valores vacíos para serFalse
.Consulte emulación de tipos numéricos para obtener más información sobre la anulación.
Ejemplos:
En lugar de verificar el argumento es un Número (¡muy poco python, amirite!) Podríamos proporcionar un valor 0 predeterminado y luego intentar la operación:
fuente
Tarde a la fiesta, pero por profundidad arbitraria me encontré haciendo algo como esto:
El truco aquí es básicamente hacer de la
DeepDict
instancia en sí una fábrica válida para construir valores perdidos. Ahora podemos hacer cosas comofuente
No hay errores de nuevo. No importa cuántos niveles anidados. pop sin error también
dd = DefaultDict ({"1": 333333})
fuente