为什么OrderedDict不使用super?

时间:2016-09-13 20:48:11

标签: python oop multiple-inheritance super python-collections

我们可以通过使用多重继承来轻松创建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

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

也就是说,魔术是有效的,因为

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

super来电必须在父母和父母之前根据兄弟姐妹进行委托。 mro的规则,自定义类使用OrderedDict作为存储后端。

然而,一位同事最近惊讶地指出,OrderedDict doesn't使用超级:

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明确调用dict.__setitem__

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

1 个答案:

答案 0 :(得分:0)

这是一种微观优化。查找dict_setitem参数比查找dict.__setitem__super().__setitem__略快。

如果你有另一个覆盖__setitem__的类,这可能会导致多重继承问题,但OrderedDict并不是为那种钻石结构方法覆盖而设计的。要使OrderedDict能够支持这一点,它必须非常谨慎地保证,如果他们在订购信息不一致时尝试索引OrderedDict,那么另一个类的方法可能会看到什么字典结构。这样的保证太麻烦了。