4

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

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

如果我错了,请纠正我,但这主要取决于使用的Counter事实super

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

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

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

调用必须根据mrosuper“父母之前的兄弟姐妹”规则进行委托,因此自定义类使用 an作为存储后端。 OrderedDict

然而,一位同事最近指出,令我惊讶的是,OrderedDict 它不使用 super:

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 中的下一个行?

4

1 回答 1

0

这是一个微优化。查找dict_setitem参数比查找dict.__setitem__或稍快super().__setitem__

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

于 2016-09-13T21:02:10.863 回答