包装python di时保留引用

2024-06-10 01:43:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在python3中编写一个dict子类,如果请求的值恰好是dict,它会包装一些dict方法并返回相同类的实例,而不是__getitem__上的dict。否则,我希望行为与dict完全相同。这就是我想到的:

class WrappedDict(dict):
    def __init__(self, stuff, *args, **kwargs):
        super(WrappedDict, self).__init__(*args, **kwargs)
        self.stuff = stuff

    def update_stuff(self):
        pass  # Do things with stuff

    def update(self, *args, **kwargs):
        self.update_stuff(*args, **kwargs)
        super(WrappedDict, self).update(*args, **kwargs)

    def __getitem__(self, item):
        obj = super(WrappedDict, self).__getitem__(item)
        if isinstance(obj, dict):
            return WrappedDict(self.stuff + str(item), obj)
        else:
            return obj

但是,这与dict不同,因为它不返回对dict值的引用,而是从该dict创建的新对象。为了说明我的意思:

d1 = {'a': 1, 'b': 2, 'c': {'d': 4}}
d1.update(a=10)
d2 = d1['c']
d2.update(d=40)
print(d1)

将给出:

{'a': 10, 'b': 2, 'c': {'d': 40}}

但对WrappedDict也是这样:

wd1 = WrappedDict("stuff", {'a': 1, 'b': 2, 'c': {'d': 4}})
wd1.update(a=10)
wd2 = wd1['c']
wd2.update(d=40)
print(wd1)

提供:

{'a': 10, 'b': 2, 'c': {'d': 4}}

注4,而不是预期的40。有没有办法复制以前的行为没有太多的黑魔法


Tags: selfobjinitdefargsupdateitemdict
1条回答
网友
1楼 · 发布于 2024-06-10 01:43:53

使用__setitem__将新创建的WrappedDict设置回对象:

def __getitem__(self, item):
    obj = super(WrappedDict, self).__getitem__(item)
    if isinstance(obj, dict):
        wrapped = WrappedDict(self.stuff + str(item), obj)
        super(WrappedDict, self).__setitem__(item, wrapped)
        return wrapped
    else:
        return obj

完整代码:

class WrappedDict(dict):
    def __init__(self, stuff, *args, **kwargs):
        super(WrappedDict, self).__init__(*args, **kwargs)
        self.stuff = stuff

    def update_stuff(self, *args, **kwargs):
        pass  # Do things with stuff

    def update(self, *args, **kwargs):
        self.update_stuff(*args, **kwargs)
        super(WrappedDict, self).update(*args, **kwargs)

    def __getitem__(self, item):
        obj = super(WrappedDict, self).__getitem__(item)
        if isinstance(obj, dict):
            wrapped = WrappedDict(self.stuff + str(item), obj)
            super(WrappedDict, self).__setitem__(item, wrapped)
            return wrapped
        else:
            return obj

d1 = {'a': 1, 'b': 2, 'c': {'d': 4}}
d1.update(a=10)
d2 = d1['c']
d2.update(d=40)
print(d1)

wd1 = WrappedDict("stuff", {'a': 1, 'b': 2, 'c': {'d': 4}})
wd1.update(a=10)
wd2 = wd1['c']
wd2.update(d=40)
print(wd1)

输出:

{'a': 10, 'b': 2, 'c': {'d': 40}}
{'a': 10, 'b': 2, 'c': {'d': 40}}

相关问题 更多 >