为什么 OrderedDict 不使用 super ?

2024-01-28

我们可以创建一个OrderedCounter简单地通过使用多重继承:

>>> from collections import Counter, OrderedDict
>>> class OrderedCounter(Counter, OrderedDict): 
...     pass
...
>>> OrderedCounter('Mississippi').items()
[('M', 1), ('i', 4), ('s', 4), ('p', 2)]

如果我错了,请纠正我,但这关键取决于以下事实:Counter uses super https://github.com/python/cpython/blob/761d139852063b9aa3caf58023184c4a399d594f/Lib/collections/__init__.py#L533:

class Counter(dict):
    def __init__(*args, **kwds):
        ...
        super(Counter, self).__init__()
        ...

也就是说,这个魔术之所以有效,是因为

>>> OrderedCounter.__mro__
(__main__.OrderedCounter,
 collections.Counter,
 collections.OrderedDict,
 dict,
 object)

The super呼叫必须根据“兄弟姐妹先于父母”的规则进行委派mro https://www.python.org/download/releases/2.3/mro/,因此自定义类使用OrderedDict作为存储后端。

然而,令我惊讶的是,最近一位同事指出,OrderedDict doesn't https://github.com/python/cpython/blob/761d139852063b9aa3caf58023184c4a399d594f/Lib/collections/__init__.py#L107-L119使用超级:

def __setitem__(self, key, value,
                dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
    ... 
    # <some weird stuff to maintain the ordering here>
    dict_setitem(self, key, value)

起初我以为这可能是因为OrderedDict先来的,雷蒙德后来也懒得去改,但看起来super早于OrderedDict.

为什么OrderedDict call dict.__setitem__明确地?

为什么它需要是一个 kwarg?这在使用时不会造成麻烦吗OrderedDict在钻石继承的情况下,因为它直接传递给父类而不是委托给 mro 中的下一个?


这是一个微观优化。查找一个dict_setitem争论比查找略快dict.__setitem__ or super().__setitem__.

如果您有另一个类重写,这可能会导致多重继承问题__setitem__, but OrderedDict无论如何,它并不是为那种菱形结构的方法而设计的。为了OrderedDict为了支持这一点,它必须非常仔细地保证另一个类的方法在尝试索引时可能会看到什么OrderedDict而排序信息与dict结构不一致。这样的保证太混乱了,无法做出。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 OrderedDict 不使用 super ? 的相关文章

随机推荐