编程语言
首页 > 编程语言> > python – 创建有序计数器

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.

解决方法:

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 __()时,它按顺序搜索类: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’)这样的语句,会发生更有趣的调用序列.首先,调用Counter.update(). Counter.update()的代码使用self [elem],后者变成对OrderedDict .__ setitem __()的调用.并且该代码调用dict .__ setitem __().

如果基类反转,则不再有效.因为mro是不同的,并且调用了错误的方法.

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

有关mro的更多信息,请参阅Python 2.3 documentation.

标签:ordereddictionary,python,python-3-x,dictionary,counter
来源: https://codeday.me/bug/20190917/1810124.html