子类化字典__getitem__,同时保持原始类类型

8 浏览
0 Comments

子类化字典__getitem__,同时保持原始类类型

我试图在访问哈希时继承Python字典的__getitem__方法,同时保持原始类类型。在properly subclassingperfect overriding中没有找到解决这个问题的答案。例如,\n

class MyDict(dict):
    def __init__(self, data=None):
        if not data:
            data = {}
        dict.__init__(self, data)
    def __getitem__(self, key):
        if key == 'b':
            print('找到了 "b"')
        return dict.__getitem__(self, key)
shallow_dict = MyDict(data={
    'b': 'value'
})
# 正如预期,打印出 Found "b"
x = shallow_dict['b']
deep_dict = MyDict(data={
    'a': {
        'b': 'value'
    }
})
# 什么也没有打印
x = deep_dict['a']['b']

\n这是因为当我们访问 [\'b\'] 时,我们实际上是在访问一个 dict,而不是 MyDict。所以我试图通过将内容复制到一个新对象来解决这个问题:\n

def __getitem__(self, key):
    data = dict.__getitem__(self, key)
    if key == 'b':
        print('找到了 "b"')
    if isinstance(data, dict):
        return MyDict(data)
    return data

\n然而,这种解决方法在写入哈希内容时导致了一个新问题,因为我返回的是一个副本而不是引用:\n

deep_dict['a']['b'] = 'other value'
# 打印出 'value'
print(deep_dict['a']['b'])

\n有关如何正确保持类型的建议吗?因为复制产生了这种副作用。

0
0 Comments

问题的原因是在MyDict类的__getitem__方法中,当获取self.data时,它只是将self.data.__getitem__的结果通过引用传递给一个新的MyDict对象。这导致了在访问嵌套字典时的问题,因为每次访问都会返回一个新的MyDict对象,而不是原始的字典对象。

为了解决这个问题,可以将MyDict类改为继承自dict,而不是使用代理的方式。这样,在__getitem__方法中可以直接返回self.data.__getitem__(key)的结果,而不需要创建新的MyDict对象。这样就可以保持原始的字典对象类型。

下面是修改后的代码:

class MyDict(dict):
    def __init__(self, data={}):
        super().__init__(data)
        
    def __getitem__(self, key):
        if key == 'b':
            print('Found "b"')
        return super().__getitem__(key)
    
shallow_dict = MyDict({
    'b': 'value'
})
x = shallow_dict['b']
deep_dict = MyDict({
    'a': {
        'b': 'value'
    }
})
x = deep_dict['a']['b']
# assignment
deep_dict['a']['a'] = {'b': 'here'}
deep_dict['a']['a']['b']
print(deep_dict)

输出结果为:

Found "b"
Found "b"
Found "b"
{'a': {'b': 'value', 'a': {'b': 'here'}}}

通过继承dict类,我们可以直接使用dict的所有方法,避免了需要单独实现所有dict方法的问题。这样就解决了原始问题,并且保持了原始字典对象的类型。

0