大家圣诞快乐
我正在实现一个允许属性访问的自定义字典,例如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)
如评论中所述,最后一次测试失败了。有人知道怎么修吗
根据这个问题的答案:star unpacking for own classes,我想我需要从collections.abc.Mapping
和dict
继承。然而,这并没有解决问题
我在想这可能和我不太清楚的MRO有关。但不管我把类定义改成
class DotDict(Mapping, item):
或者
class DotDict(item, Mapping):
我的测试不会变绿
您所面临的问题是,yu正在尝试构建一个本机的
dict
——对于这个类,__getitem__
只是检索其值的几种方法之一。由于在Python中实现dict的方式,出于历史和性能的原因,有很多方法可以完全绕过__getitem__
,因此,嵌套字典永远不会“包装”在DotDict中(例如:.values()
、items()
和星图可能会绕过这些)您真正想要的是子类collections.abc.MutableMapping——它的构造方式确保任何项检索都要经过
__getitem__
,(但是您必须实现文档中指出的方法,包括__delitem__
,__setitem__
和__iter__
-建议将实际数据作为普通词汇保存在__init__
方法中创建的.data
属性中请注意,这也使您能够更好地控制数据,例如,使您能够将数据直接包装在setitem上的自定义类中,而jsut不关心属性检索,或者相反,将任何映射存储为普通字典,以节省内存和提高效率,并在检索时将其包装
哇,试着用未注释的
__iter__
运行下面的代码非常非常奇怪
在
test_star_star_mapping_maintains_child_dot_dicts
中,您正在创建一个dict
而不是一个DotDict
,因此,重构为:将使测试通过,因为您现在正在创建
DotDict
。也许您想删除部分dict(**dot_dict)
,这样这个版本也可以工作:相关问题 更多 >
编程相关推荐