为什么OrderedDict没有使用super?

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)
super调用必须按照'siblings before parents' rule of the mro委托,因此自定义类使用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先存在,Raymond后来没有再更改它,但似乎superOrderedDict还要早。
为什么OrderedDict会显式地调用dict.__setitem__呢?
而且为什么需要成为关键字参数?当在菱形继承情况下使用OrderedDict时,这难道不会造成麻烦吗?因为它直接传递给父类,而不是委托给mro中的下一个类。
1个回答

0

这是一种微小的优化。查找 dict_setitem 参数比查找 dict.__setitem__super().__setitem__ 要稍微快一点。

如果您有另一个覆盖了 __setitem__ 的类,则这可能会在多重继承方面存在问题,但无论如何,OrderedDict 都不是为那种菱形结构的方法覆盖而设计的。如果要支持这种情况,OrderedDict 必须非常仔细地保证另一个类的方法在尝试索引 OrderedDict 时所看到的信息与 dict 结构不一致时所能看到的信息相同。这样的保证太过混乱而难以制定。


Django的QueryDict覆盖了__setitem__,而collections.OrderedDict则不支持协同继承。这种“微优化”带来的问题示例:https://stackoverflow.com/questions/23662247/can-i-make-django-querydict-preserve-ordering#comment78727560_41798570 - wim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接