我一直在阅读 super()
是如何工作的。我遇到了 这个演示如何创建有序计数器的方法:
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first seen'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__,
OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
例如:
oc = OrderedCounter('adddddbracadabra')
print(oc)
OrderedCounter(OrderedDict([('a', 5), ('d', 6), ('b', 2), ('r', 2), ('c', 1)]))
有人能够解释这是如何神奇地工作的吗?
这也出现在 Python 文档 中。
原文由 Sean 发布,翻译遵循 CC BY-SA 4.0 许可协议
OrderedCounter 在 OrderedDict 文档 中作为示例给出,并且无需覆盖任何方法即可工作:
当一个类方法被调用时,Python 必须找到正确的方法来执行。它搜索类层次结构的定义顺序称为“方法解析顺序”或 mro。 mro 存储在属性
__mro__
中:When an instance of an OrderedDict is calling
__setitem__()
, it searches the classes in order:OrderedCounter
,Counter
,OrderedDict
(where it is成立)。所以像oc['a'] = 0
这样的语句最终调用OrderedDict.__setitem__()
。相反,
__getitem__
没有被mro中的任何子类覆盖,所以count = oc['a']
由dict.__getitem__()
处理对于像
oc.update('foobar').
这样的语句,会出现一个更有趣的调用序列——首先,调用Counter.update()
。Counter.update()
的代码使用了 self[elem],它变成了对OrderedDict.__setitem__()
的调用。该代码 调用dict.__setitem__()
。如果基类被颠倒,它就不再有效。因为 mro 不同并且调用了错误的方法。
可以在 Python 2.3 文档 中找到有关 mro 的更多信息。