OrderedCounter 在中作为示例给出OrderedDict 文档,并且无需重写任何方法即可工作:
class OrderedCounter(Counter, OrderedDict):
pass
当调用类方法时,Python 必须找到正确的方法来执行。它搜索类层次结构有一个定义的顺序,称为“方法解析顺序”或 mro。 mro 存储在属性中__mro__
:
OrderedCounter.__mro__
(<class '__main__.OrderedCounter'>, <class 'collections.Counter'>, <class 'collections.OrderedDict'>, <class 'dict'>, <class 'object'>)
当 OrderedDict 的实例调用时__setitem__()
,它按顺序搜索类:OrderedCounter
, Counter
, OrderedDict
(在哪里找到的)。所以像这样的声明oc['a'] = 0
最终打电话OrderedDict.__setitem__()
.
相比之下,__getitem__
不被 MRO 中的任何子类覆盖,因此count = oc['a']
由处理dict.__getitem__()
.
oc = OrderedCounter()
oc['a'] = 1 # this call uses OrderedDict.__setitem__
count = oc['a'] # this call uses dict.__getitem__
对于类似这样的语句,会发生更有趣的调用序列oc.update('foobar').
First, Counter.update()
被叫。代码为Counter.update()
使用 self[elem],它会变成对OrderedDict.__setitem__()
。和代码that calls dict.__setitem__()
.
如果基类颠倒,它就不再起作用。因为 mro 不同并且调用了错误的方法。
class OrderedCounter(OrderedDict, Counter): # <<<== doesn't work
pass
有关 mro 的更多信息可以在 Python 2.3 中找到文档.