子类化字典__getitem__,同时保持原始类类型
子类化字典__getitem__,同时保持原始类类型
我试图在访问哈希时继承Python字典的__getitem__
方法,同时保持原始类类型。在properly subclassing或perfect 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有关如何正确保持类型的建议吗?因为复制产生了这种副作用。
问题的原因是在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方法的问题。这样就解决了原始问题,并且保持了原始字典对象的类型。