python recursion defaultdict

python - defaultdict of defaultdict, anidado



recursion (4)

¿Hay alguna manera de hacer que un defaultjudit sea el predeterminado para el defaultjudit? IOW, si lo hago:

x = defaultdict(...stuff...) x[0][1][0] {}

Eso es lo que quiero. Probablemente terminaré utilizando el patrón de grupo, pero cuando me di cuenta de que no sabía cómo hacerlo, me interesó.

Entonces, puedo hacer:

x = defaultdict(defaultdict)

pero ese es solo un nivel:

x[0] {} x[0][0] KeyError: 0

Hay recetas que pueden hacer esto. ¿Pero se puede hacer simplemente usando los argumentos normales de defaulted?

Tenga en cuenta que alguien marcó esto como un duplicado de Python: defaultdict of defaultdict? , pero esta no es la misma pregunta ... esa pregunta era cómo hacer un default de dos niveles; este es cómo hacer un defaultdict recursivo de nivel infinito.


Hay un truco ingenioso para hacer eso:

tree = lambda: defaultdict(tree)

Entonces puedes crear tu x con x = tree() .


Las otras respuestas aquí le dicen cómo crear un defaultdict que contenga "infinitamente muchos" defaultdict , pero no abordan lo que creo que pudo haber sido su necesidad inicial que era simplemente tener un defaultdict de dos profundidades.

Usted pudo haber estado buscando:

defaultdict(lambda: defaultdict(dict))

Las razones por las que podrías preferir este constructo son:

  • Es más explícito que la solución recursiva y, por lo tanto, es más comprensible para el lector.
  • Esto permite que la "hoja" del defaultdict sea ​​algo más que un diccionario, por ejemplo,: defaultdict(lambda: defaultdict(list)) o defaultdict(lambda: defaultdict(set))

Para un número arbitrario de niveles:

def rec_dd(): return defaultdict(rec_dd) >>> x = rec_dd() >>> x[''a''][''b''][''c''][''d''] defaultdict(<function rec_dd at 0x7f0dcef81500>, {}) >>> print json.dumps(x) {"a": {"b": {"c": {"d": {}}}}}

Por supuesto, también podrías hacer esto con un lambda, pero creo que las lambdas son menos legibles. En cualquier caso, se vería así:

rec_dd = lambda: defaultdict(rec_dd)


Similar a la solución de BrenBarn, pero no contiene el nombre del tree variables dos veces, por lo que funciona incluso después de los cambios en el diccionario de variables:

tree = (lambda f: f(f))(lambda a: (lambda: defaultdict(a(a))))

Luego puedes crear cada nueva x con x = tree() .

Para la versión de def , podemos usar el alcance de cierre de función para proteger la estructura de datos del defecto donde las instancias existentes dejan de funcionar si el nombre del tree se recupera. Se parece a esto:

from collections import defaultdict def tree(): def the_tree(): return defaultdict(the_tree) return the_tree()