为了举例,让我们假设我想继承 dict
并将所有键大写:
class capdict(dict):
def __init__(self,*args,**kwds):
super().__init__(*args,**kwds)
mod = [(k.capitalize(),v) for k,v in super().items()]
super().clear()
super().update(mod)
def __getitem__(self,key):
return super().__getitem__(key.capitalize())
def __setitem__(self,key,value):
super().__setitem__(key.capitalize(),value)
def __delitem__(self,key):
super().__detitem__(key.capitalize())
这在一定程度上起作用,
>>> ex = capdict(map(reversed,enumerate("abc")))
>>> ex
{'A': 0, 'B': 1, 'C': 2}
>>> ex['a']
0
但是,当然,仅适用于我记得要实现的方法,例如
>>> 'a' in ex
False
不是想要的行为。
现在,填写所有可以从“核心”派生出来的方法的懒惰方式
将混合在
collections.abc.MutableMapping
.只是,它在这里不起作用。我认为是因为所讨论的方法(示例中的 __contains__
)已经由 dict
提供了.有没有办法吃我的蛋糕并吃掉它?一些魔法让
MutableMapping
只看到我覆盖的方法,以便它基于这些重新实现其他方法?
最佳答案
您可以做什么:
这可能效果不佳(即不是最干净的设计),但您可以先从 MutableMapping 继承,然后从 dict 继承。
然后 MutableMapping 将使用您实现的任何方法(因为它们是查找链中的第一个):
>>> class D(MutableMapping, dict):
def __getitem__(self, key):
print(f'Intercepted a lookup for {key!r}')
return dict.__getitem__(self, key)
>>> d = D(x=10, y=20)
>>> d.get('x', 0)
Intercepted a lookup for 'x'
10
>>> d.get('z', 0)
Intercepted a lookup for 'z'
0
更好的方法:
最简洁的方法(易于理解和测试)是从 MutableMapping 继承,然后使用常规 dict 作为基本数据存储(使用组合而不是继承)来实现所需的方法:
>>> class CapitalizingDict(MutableMapping):
def __init__(self, *args, **kwds):
self.store = {}
self.update(*args, **kwds)
def __getitem__(self, key):
key = key.capitalize()
return self.store[key]
def __setitem__(self, key, value):
key = key.capitalize()
self.store[key] = value
def __delitem__(self, key):
del self.store[key]
def __len__(self):
return len(self.store)
def __iter__(self):
return iter(self.store)
def __repr__(self):
return repr(self.store)
>>> d = CapitalizingDict(x=10, y=20)
>>> d
{'X': 10, 'Y': 20}
>>> d['x']
10
>>> d.get('x', 0)
10
>>> d.get('z', 0)
0
>>> d['w'] = 30
>>> d['W']
30
关于python - 有没有办法从 dict 和 collections.abc.MutableMapping 一起子类化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59923717/