像访问属性一样访问字典的“值”?

7
我需要的是像这样的东西:
self.info['key'].attr2

但我不确定最优雅的方式是什么。到目前为止,我已经定义了一个类似于下面这样的字典,但它没有其中的属性。

self.info  = {}
self.info.update({'key':
                        {'attr1':   2,
                         'attr2':   lambda: self.func(arg1)}
                       })

但是我需要这样使用它:

但是我需要像这样使用它:

self.info['key']['attr2']()

请注意,我想要的是像属性一样访问字典值。 这个线程 有一个答案,也可以在我的情况下使用,即我将上面的子字典制作为对象,并将其作为值赋给主字典。
但我想知道是否有更好的方法,也许可以使用装饰器,并且代码行数更少,甚至可以不使用字典来完成像我在第一行描述的操作,或者更好地完成此操作:
self['key'].attr2

2
collections.namedtuple,就像你在链接中提到的那样? - dspencer
1
或类似于此--> https://github.com/Infinidat/munch - gold_cy
这个回答解决了你的问题吗?像访问属性一样访问字典键? - Friedrich -- Слава Україні
你为什么想要这样做? - AMC
4个回答

7

这是一个简短的包装器,可将字典键作为属性访问:

class nameddict(dict):
   __getattr__ = dict.__getitem__

info = nameddict()
info['key'] = nameddict(attr1=2, attr2=3)

然后 info['key'].attr2 以及 info['key']['attr2']info.key.attr2 都返回 3


4

如果您想要一个更加动态的容器,不需要像命名元组一样声明属性,则可以使用SimpleNamespace对象。

from types import SimpleNamespace as ns
info  = {}
info.update({'key': ns(attr1=2, attr2=lambda x: x+1)})

1
这只是Python 3。 - Friedrich -- Слава Україні
@Lior 如果在开始时将字符串“attr1”和“attr2”作为名称给我,那该怎么办? - azerila
在大规模使用SimpleNameSpace时,这真的是一种安全的方式吗? - matanster
@Friedrich--СлаваУкраїні 这是2020年(现在是2023年)...当然是Python 3,跟上时代啊! - undefined

2

你可以使用collections.namedtuple,正如你所链接的帖子中建议的那样:

Attrs = namedtuple("Attrs", ["attr1", "attr2"])
info = {"key": Attrs(attr1=2, attr2=lambda: 4)}
info["key"].attr2()

0

有一个叫做Box的库非常方便。 https://pypi.org/project/python-box/

它处理各种边缘情况,例如字典内嵌字典和列表等。

pip install python-box

from box import Box

movie_box = Box({
    "Robin Hood: Men in Tights": {
        "imdb_stars": 6.7,
        "length": 104,
        "stars": [ {"name": "Cary Elwes", "imdb": "nm0000144", "role": "Robin Hood"},
                   {"name": "Richard Lewis", "imdb": "nm0507659", "role": "Prince John"} ]
    }
})

movie_box.Robin_Hood_Men_in_Tights.imdb_stars
# 6.7

movie_box.Robin_Hood_Men_in_Tights.stars[0].name
# 'Cary Elwes'



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接