为什么 Counter.__iadd__ 比 Counter.update 慢那么多?

我试验Counter.__iadd__并Counter.update累积了 10,000 个计数器,结果证明__iadd__需要 1.8 秒才能完成,而update只需要 36 毫秒。


我想知道为什么__iadd__要花这么多时间。我猜它首先创建一个新对象并将该对象复制到自身。但它为什么要这样做呢?不是到位了吗?我不知道为什么它不使用与update.


这是我在 IPython 中的实验:


[ins] In [11]: def update():

          ...:     a = Counter()

          ...:     for i in range(10000):

          ...:         a.update(Counter([i]))

          ...:

          ...: %time update()

CPU times: user 36 ms, sys: 0 ns, total: 36 ms

Wall time: 33.3 ms


[nav] In [12]: def iadd():

          ...:     a = Counter()

          ...:     for i in range(10000):

          ...:         a.__iadd__(Counter([i]))

          ...:

          ...: %time iadd()

CPU times: user 1.8 s, sys: 0 ns, total: 1.8 s

Wall time: 1.8 s


四季花海
浏览 121回答 1
1回答

泛舟湖上清波郎朗

你的假设是不正确的。__iadd__不会创建新的计数器。速度变慢是因为多重集运算符collections.Counter 过滤掉了非正计数的条目,这需要每次都遍历整个计数器:提供了几种数学运算,用于组合 Counter 对象以生成多重集(计数大于零的计数器)。加法和减法通过添加或减去相应元素的计数来组合计数器。交集和并集返回相应计数的最小值和最大值。每个操作都可以接受带符号计数的输入,但输出将排除计数为零或更少的结果。update不那样做。此外,__iadd__是一个用于覆盖+=行为的挂钩。您几乎不应该手动调用它;你应该使用+=(或者update,在这种情况下,或者只是a[i] += 1)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python