python - 有没有办法从 dict 和 collections.abc.MutableMapping 一起子类化?

标签 python python-3.x

为了举例,让我们假设我想继承 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/

相关文章:

python - 从列表中创建元组的元组的更优雅的方式

python - 重构游戏的 "to hit"值

python - 在 python 中使用多处理优化大数组的处理

python - ASCII 字符串作为 Python 3 中 numpy 字符串数组的 dtype

python-3.x - ImageIO 中的质量损失

python - 使用纹理可视化 3D 模型

python - 多数元素 python

python - 在 tqdm 中的 for 循环后更改描述

python-3.x - 使用matplotlib将文本文件中的字符串转换为绘图

python - Caffe 迭代损失与训练净损失