我们可以通过使用多重继承来轻松创建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中的下一行?
答案 0 :(得分:0)
这是一种微观优化。查找dict_setitem
参数比查找dict.__setitem__
或super().__setitem__
略快。
如果你有另一个覆盖__setitem__
的类,这可能会导致多重继承问题,但OrderedDict
并不是为那种钻石结构方法覆盖而设计的。要使OrderedDict
能够支持这一点,它必须非常谨慎地保证,如果他们在订购信息不一致时尝试索引OrderedDict
,那么另一个类的方法可能会看到什么字典结构。这样的保证太麻烦了。