创建有序委员会

2024-05-20 23:08:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在研究super()是如何工作的。我遇到了演示如何创建有序计数器的this recipe

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 documentation中。


Tags: fromselfreturndefcounter计数器recipethis
1条回答
网友
1楼 · 发布于 2024-05-20 23:08:59

OrderedCounter是OrderedDict documentation中的一个示例,不需要重写任何方法即可工作:

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__()时,它将按以下顺序搜索类:OrderedCounterCounterOrderedDict(找到它的位置)。所以像oc['a'] = 0这样的语句最终会调用OrderedDict.__setitem__()

相反,mro中的任何子类都不会重写__getitem__,因此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__()的调用。的代码调用dict.__setitem__()

如果基类被反转,它将不再工作。因为mro是不同的,调用错误的方法。

class OrderedCounter(OrderedDict, Counter):   # <<<== doesn't work
    pass

有关mro的更多信息可以在Python 2.3documentation中找到。

相关问题 更多 >