微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

链接 __getitem__ (d['a']['b']) 不适用于自定义 dict 包装器

如何解决链接 __getitem__ (d['a']['b']) 不适用于自定义 dict 包装器

我有一本字典,其中每个键总是以特定字符串开头。 dict 可以是这样的:

d = {
    "aa123":{
        "aa456": "456","aa789": "789"
    }
}

所以我正在编写一个包装器,我可以在不使用前置字符串的情况下查询字典。例如:

print(d["123"]["456"]) # --> should print "456"

这是我的包装器:

class CustDict(dict):
    def __init__(self,*args,**kwargs):
        self.ns = kwargs.pop("namespace")
        super().__init__(*args,**kwargs)

    def __getitem__(self,key):
        key = f"{self.ns}{key}"
        return super().__getitem__(key)

当我使用它时,我收到以下错误

cust_d = CustDict(d,namespace="aa")
print(cust_d["123"]["456"])

我收到错误

KeyError: '456'

现在,我知道这是因为 __getitem__ 返回的是 dict 而不是 CustDict 的实例。 但是,如果我将 return super().__getitem__(key) 替换为 return CustDict(k,namespace=self.ns),则会出现其他错误,例如 ValueError: dictionary update sequence element #0 has length 1; 2 is required

对此的任何解决方案将不胜感激。

解决方法

首先,既然您想覆盖 __getitem__ 的实例方法,那么您不应该从 dict 继承子类。如果您从 dict 继承,那么它甚至不会查看 __getitem__ 的实例方法。您可以了解更多关于 here 的信息。而是使用 UserDict

对您的代码稍作修改,然后使其如下所示:

from collections import UserDict

class CustDict(UserDict):
    def __init__(self,*args,**kwargs):
        self.ns = kwargs.pop("namespace")
        super().__init__(*args,**kwargs)

    def __getitem__(self,key):
        key = f"{self.ns}{key}"
        val = super().__getitem__(key)
        if isinstance(val,dict):
            return CustDict(val,namespace=self.ns)
        else:
            return val

cust_d = CustDict(d,namespace="aa")

cust_d["123"]
>> {'aa456': '456','aa789': '789'}

cust_d["123"]["456"]
>> '456'

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。