Voici une solution similaire à chrisz, mais vous n'avez pas à quoi que ce soit à votre dict a-avant. :
class dictDotter(dict):
def __getattr__(self,key):
val = self[key]
return val if type(val) != dict else dictDotter(val)
et juste x=dictDotter(originalDict)
qui vous permettra d'avoir arbitraire dot obtenir (`x.d'abord.la seconde...). Je note c'est deux fois plus lent que chrisz solution, et le son est 9 fois plus lent que le vôtre (sur ma machine, environ).
Donc, si vous insistez pour faire ce travail @tdelaney semble avoir fourni le seul véritable amélioration de la performance.
Une autre option qui fait mieux que ce que vous avez (en termes de temps d'exécution):
class dictObjecter:
def __init__(self,adict):
for k,v in adict.items():
self.__dict__[k] = v
if type(v) == dict: self.__dict__[k] = dictObjecter(v)
qui vont faire un objet de votre dict, de sorte que la notation point est d'habitude. Cela permettra d'améliorer les temps d'exécution à 3 fois ce que vous avez, pas mal, mais au prix d'aller sur vos dict, et de le remplacer par autre chose.
Voici le total de tests de code:
from timeit import timeit
class dictObjecter:
def __init__(self,adict):
for k,v in adict.items():
self.__dict__[k] = v
if type(v) == dict: self.__dict__[k] = dictObjecter(v)
class dictDotter(dict):
def __getattr__(self,key):
val = self[key]
return val if type(val) != dict else dictDotter(val)
def get_entry(dict, keyspec):
keys = keyspec.split('.')
result = dict[keys[0]]
for key in keys[1:]:
result = result[key]
return result
class dotdict(dict):
"""dot.notation access to dictionary attributes"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def dct_to_dotdct(d):
if isinstance(d, dict):
d = dotdict({k: dct_to_dotdct(v) for k, v in d.items()})
return d
x = {'a':{'b':{'c':{'d':1}}}}
y = dictDotter(x)
z = dct_to_dotdct(x)
w = dictObjecter(x)
print('{:15} : {}'.format('dict dotter',timeit('y.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('dot dict',timeit('z.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('dict objecter',timeit('w.a.b.c.d',globals=locals(),number=1000)))
print('{:15} : {}'.format('original',timeit("get_entry(x,'a.b.c.d')",globals=locals(),number=1000)))
print('{:15} : {:.20f}'.format('best ref',timeit("x['a']['b']['c']['d']",globals=locals(),number=1000)))
Je fournis le dernier de recherche comme le meilleur de référence.Les résultats sur un ordinateur Windows Ubuntu sous-système:
dict dotter : 0.0035500000003594323
dot dict : 0.0017939999997906853
dict objecter : 0.00021699999979318818
original : 0.0006629999998040148
best ref : 0.00007999999979801942
de sorte que le est objectivé dict est 3 fois plus lent que régulièrement une recherche dans le dictionnaire - donc, si la vitesse est importante, pourquoi voudriez-vous cela?