python - 创建有序计数器

标签 python python-3.x dictionary counter ordereddictionary

我一直在阅读 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__() 时,它会按顺序搜索类:OrderedCounterCounter 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__() 的调用。 that 的代码调用 dict.__setitem__()

如果基类颠倒了,它就不再起作用了。因为 mro 不同,调用了错误的方法。

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

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

关于python - 创建有序计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35446015/

相关文章:

python - 使用 Moviepy 获取剪辑中的帧数

python - 如何使用正则表达式查找字符串中的重复字符

python - 可以使用单个点分隔的字符串路径设置 Python 嵌套字典项吗?

c# - C# 字典只存储对象的引用还是作为键添加的对象的完整副本?

python - Raspberry Pi 在引导期间关闭

在 Keras 中执行分层 KFold 交叉验证的 Python 库

python - 关于 C 溢出,如何在 Python 中使用 64 位无符号整数数学?

python - 将高斯混合转换为 PyMC3

python - 无法获取 Gtk.ListBox() 对象以在运行时在 Python 中添加新的 Gtk.ListBoxRow() 对象

sql - SQL 字典表是否应该有 IDENTITY 列