Доступ к dict "значениям" как атрибут? - PullRequest
6 голосов
/ 14 марта 2020

То, что я ищу, имеет что-то вроде этого:

self.info['key'].attr2

Но я не уверен, что было бы самым элегантным способом добиться этого. Пока что я определил словарь, как показано ниже, но у меня нет атрибутов из него.

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

Но тогда мне придется использовать его следующим образом:

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

Обратите внимание, что я ищу доступ к значениям словаря, как атрибуты. В этой теме есть ответ, который может быть использован в моем случае также, вероятно, что я делаю объект из под-словаря сверху и передаю его в качестве значения в основной словарь.

Но мне интересно, есть ли более хороший способ, возможно, с декораторами и с меньшим количеством строк кода, и, возможно, даже без использования словарей, что-то вроде того, что я описал в первой строке, возможно, даже лучше, например:

self['key'].attr2

Ответы [ 4 ]

3 голосов
/ 14 марта 2020

если вам нужен более динамический c контейнер, для которого вам не нужно объявлять атрибуты, как в namedtuple, вы можете использовать объект SimpleNamespace.

from types import SimpleNamespace as ns
info  = {}
info.update({'key': ns(attr1=2, attr2=lambda x: x+1)})
3 голосов
/ 14 марта 2020

Вот короткая оболочка для доступа к ключам dict как атрибутам:

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.

2 голосов
/ 14 марта 2020

Вы можете использовать collections.namedtuple, как указано в теме, которую вы связываете:

Attrs = namedtuple("Attrs", ["attr1", "attr2"])
info = {"key": Attrs(attr1=2, attr2=lambda: 4)}
info["key"].attr2()
0 голосов
/ 22 марта 2020

Есть библиотека для этого, которая называется Box. Очень удобно. https://pypi.org/project/python-box/

Он обрабатывает все виды граничных случаев, например, словари внутри словарей и списков и т. Д. c.

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'


...