С Рождеством всех,
Я реализую пользовательский словарь, который разрешает доступ к атрибутам, например, dct.attribute
.Словари могут быть вложенными, поэтому dct.nested_dct.attribute
также должно быть возможно.Это уже работает довольно хорошо, за исключением распаковки звезда-звезда.Я думаю, что я могу выразить то, что я пытаюсь сделать лучше, используя код, чем слова.Итак, вот класс, который я пишу.Тесты должны достаточно четко объяснить, что они делают:
class DotDict(dict):
def __getattr__(self, item):
return self.__getitem__(item)
def __getitem__(self, item):
item = super().__getitem__(item)
if isinstance(item, dict):
return self.__class__(item)
return item
class TestDotDict:
@pytest.fixture
def dot_dict(self):
input_dict = dict(
a=1,
b=dict(
c=2,
d=3,
)
)
return DotDict(input_dict)
def test_can_access_by_dot(self, dot_dict):
assert dot_dict.a == 1
def test_returned_dicts_are_dot_dicts(self, dot_dict):
b_dict = dot_dict["b"]
assert isinstance(b_dict, DotDict)
assert b_dict.c == 2
def test_getting_item_also_returns_dot_dicts(self, dot_dict):
b_dict = dot_dict["b"]
assert isinstance(b_dict, DotDict)
assert b_dict.c == 2
def test_unpack_as_function_arguments_yields_dot_dicts_for_children(self, dot_dict):
# this is failing
def checker(a, b):
assert a == 1
assert b.c == 2
checker(**dot_dict)
Как указано в комментарии, последний тест не пройден.Кто-нибудь знает, как это исправить?
После ответов на этот вопрос: звезда распаковывается для собственных классов , я решил, что мне нужно наследовать от collections.abc.Mapping
и dict
.Однако это не решило проблему.
Я думал, что это может быть связано с MRO, которое мне не совсем понятно.Но независимо от того, изменю ли я определение класса на
class DotDict(Mapping, item):
или
class DotDict(item, Mapping):
, мои тесты не станут зелеными.