Je veux créer une structure polymorphe qui peut être créée à la volée avec un effort de frappe minimum et être très lisible. Par exemple:Dictionnaires imbriqués en Python, avec création implicite de conteneurs intermédiaires non existants?
a.b = 1
a.c.d = 2
a.c.e = 3
a.f.g.a.b.c.d = cucu
a.aaa = bau
Je ne veux pas créer un récipient intermédiaire tel que:
a.c = subobject()
a.c.d = 2
a.c.e = 3
Ma question est semblable à celui-ci:
What is the best way to implement nested dictionaries?
Mais je ne suis pas heureux avec la solution là parce que je pense qu'il y a un bug:
Les articles seront créés même quand vous ne voulez pas: supposer e vous voulez comparer 2 structures polymorphes: cela créera dans la 2ème structure n'importe quel attribut qui existe dans le premier et qui est juste vérifié dans l'autre. par exemple:
a = {1:2, 3: 4}
b = {5:6}
# now compare them:
if b[1] == a[1]
# whoops, we just created b[1] = {} !
Je veux aussi obtenir la plus simple notation possible
a.b.c.d = 1
# neat
a[b][c][d] = 1
# yuck
J'ai essayé de tirer de la classe d'objet ... mais je ne pouvais pas éviter de laisser le même bug que ci-dessus où les attributs sont nés juste en essayant de les lire: simple dir() tenterait de créer des attributs tels que « méthodes » ... comme dans cet exemple, ce qui est évidemment cassé:
class KeyList(object):
def __setattr__(self, name, value):
print "__setattr__ Name:", name, "value:", value
object.__setattr__(self, name, value)
def __getattribute__(self, name):
print "__getattribute__ called for:", name
return object.__getattribute__(self, name)
def __getattr__(self, name):
print "__getattr__ Name:", name
try:
ret = object.__getattribute__(self, name)
except AttributeError:
print "__getattr__ not found, creating..."
object.__setattr__(self, name, KeyList())
ret = object.__getattribute__(self, name)
return ret
>>> cucu = KeyList()
>>> dir(cucu)
__getattribute__ called for: __dict__
__getattribute__ called for: __members__
__getattr__ Name: __members__
__getattr__ not found, creating...
__getattribute__ called for: __methods__
__getattr__ Name: __methods__
__getattr__ not found, creating...
__getattribute__ called for: __class__
Merci, vraiment!
p.s .: la meilleure solution que je trouve à ce jour est:
class KeyList(dict):
def keylset(self, path, value):
attr = self
path_elements = path.split('.')
for i in path_elements[:-1]:
try:
attr = attr[i]
except KeyError:
attr[i] = KeyList()
attr = attr[i]
attr[path_elements[-1]] = value
# test
>>> a = KeyList()
>>> a.keylset("a.b.d.e", "ferfr")
>>> a.keylset("a.b.d", {})
>>> a
{'a': {'b': {'d': {}}}}
# shallow copy
>>> b = copy.copy(a)
>>> b
{'a': {'b': {'d': {}}}}
>>> b.keylset("a.b.d", 3)
>>> b
{'a': {'b': {'d': 3}}}
>>> a
{'a': {'b': {'d': 3}}}
# complete copy
>>> a.keylset("a.b.d", 2)
>>> a
{'a': {'b': {'d': 2}}}
>>> b
{'a': {'b': {'d': 2}}}
>>> b = copy.deepcopy(a)
>>> b.keylset("a.b.d", 4)
>>> b
{'a': {'b': {'d': 4}}}
>>> a
{'a': {'b': {'d': 2}}}
Demandez-vous au sujet de 'collections.defaultdict'? –
J'ai ajouté un exemple de classe dérivé de dict. C'est aussi proche que je pouvais obtenir ce que je voulais. – RumburaK