with programiz functions examples dictionaries create accessing python dictionary nested

programiz - Diccionario infinitamente anidado en Python



python dictionary of dictionaries (6)

Esto está cerca:

class recursivedefaultdict(defaultdict): def __init__(self, attrFactory=int): self.default_factory = lambda : type(self)(attrFactory) self._attrFactory = attrFactory def __getattr__(self, attr): newval = self._attrFactory() setattr(self, attr, newval) return newval d = recursivedefaultdict(float) d[''abc''][''def''][''xyz''].count += 0.24 d[''abc''][''def''][''xyz''].total += 1 data = [ (''A'',''B'',''Z'',1), (''A'',''C'',''Y'',2), (''A'',''C'',''X'',3), (''B'',''A'',''W'',4), (''B'',''B'',''V'',5), (''B'',''B'',''U'',6), (''B'',''D'',''T'',7), ] table = recursivedefaultdict(int) for k1,k2,k3,v in data: table[k1][k2][k3] = v

No es exactamente lo que quiere, ya que el nivel más anidado no tiene sus valores 0 predeterminados para ''contar'' o ''total''.

Editado: Ah, esto funciona ahora - solo necesitaba agregar un método __getattr__ , y esto hace lo que quiere.

Editar 2: ahora puede definir otros métodos de fábrica para los atributos, además de los enteros. Pero todos tienen que ser del mismo tipo, no pueden tener el conteo ser flotante y el total ser int.

¿Alguien sabe si hay una clase estándar para un diccionario infinitamente encajable en Python?

Me encuentro repitiendo este patrón:

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) d[''abc''][''def''][''xyz''] += 1

Si deseo agregar "otra capa" (por ejemplo, d[''abc''][''def''][''xyz''][''wrt''] ), tengo que definir otra anidación de los predeterminados.

Para generalizar este patrón, he escrito una clase simple que anula __getitem__ para crear automáticamente el siguiente diccionario anidado.

p.ej

d = InfiniteDict((''count'',0),(''total'',0)) d[''abc''][''def''][''xyz''].count += 0.24 d[''abc''][''def''][''xyz''].total += 1 d[''abc''][''def''][''xyz''][''wrt''].count += 0.143 d[''abc''][''def''][''xyz''][''wrt''].total += 1

Sin embargo, ¿alguien sabe de una implementación preexistente de esta idea? He intentado con Google, pero no estoy seguro de cómo se llamaría.


Esto se presta naturalmente a una definición recursiva.

>>> import collections >>> def nested_dd(): ... return collections.defaultdict(nested_dd) ... >>> foo = nested_dd() >>> foo defaultdict(<function nested_dd at 0x023F0E30>, {}) >>> foo[1][2]=3 >>> foo[1] defaultdict(<function nested_dd at 0x023F0E30>, {2: 3}) >>> foo[1][2] 3


La solución ideal, inspirada en la respuesta de sth:

from collections import defaultdict class InfiniteDict(defaultdict): def __init__(self, **kargs): defaultdict.__init__(self, lambda: self.__class__(**kargs)) self.__dict__.update(kargs) d = InfiniteDict(count=0, total=0) d[''abc''][''def''].count += 0.25 d[''abc''][''def''].total += 1 print d[''abc''][''def''].count print d[''abc''][''def''].total d[''abc''][''def''][''xyz''].count += 0.789 d[''abc''][''def''][''xyz''].total += 1 print d[''abc''][''def''][''xyz''].count print d[''abc''][''def''][''xyz''].total


Puede derivar de defaultdict para obtener el comportamiento que desea:

class InfiniteDict(defaultdict): def __init__(self): defaultdict.__init__(self, self.__class__) class Counters(InfiniteDict): def __init__(self): InfiniteDict.__init__(self) self.count = 0 self.total = 0 def show(self): print "%i out of %i" % (self.count, self.total)

El uso de esta clase se vería así:

>>> d = Counters() >>> d[1][2][3].total = 5 >>> d[1][2][3].show() 0 out of 5 >>> d[5].show() 0 out of 0


Simplemente se llama "un árbol". Hay un módulo que parece hacer lo que quieres.


Creo que este one-liner es una solución casi perfecta:

>>> from collections import defaultdict >>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict) >>> d = infinite_defaultdict() >>> d[''x''][''y''][''z''] = 10

por Raymond Hettinger en Twitter ( https://twitter.com/raymondh/status/343823801278140417 )