【发布时间】:2012-03-11 09:41:35
【问题描述】:
在 CSP 样式进程的异常处理程序中,我需要读取并丢弃通道的全部内容,以允许其他阻塞的进程向它发送数据。接口呈现一个生成器用于接收,有没有比下面的更快的方式来消耗和丢弃一个生成器的全部内容?
for _ in chan:
pass
【问题讨论】:
标签: python python-3.x generator
在 CSP 样式进程的异常处理程序中,我需要读取并丢弃通道的全部内容,以允许其他阻塞的进程向它发送数据。接口呈现一个生成器用于接收,有没有比下面的更快的方式来消耗和丢弃一个生成器的全部内容?
for _ in chan:
pass
【问题讨论】:
标签: python python-3.x generator
有一种方法稍微快一点:
collections.deque(chan, maxlen=0)
不过,您的代码使意图更加清晰,因此您应该衡量是否存在明显差异。我几乎总是更喜欢你的代码。
(不过,我永远不会使用 _ 作为变量名。它往往会让人感到困惑,与交互式 shell 中的 _ 以及常见的 gettext 别名发生冲突。)
编辑:以下是一些简单的时间安排:
In [1]: import collections
In [2]: a = range(100000)
In [3]: timeit reduce(lambda _, __: None, a)
100 loops, best of 3: 13.5 ms per loop
In [4]: timeit for dummy in a: pass
1000 loops, best of 3: 1.75 ms per loop
In [5]: timeit collections.deque(a, maxlen=0)
1000 loops, best of 3: 1.51 ms per loop
【讨论】:
_ 是一次性变量的通用名称,我想。
dummy,您将避免任何混淆。
python.org 上根本没有提到它。我已经被问了几十次这种奇怪的语法是什么意思。显然,没有人问过我为什么将未使用的变量称为 dummy 或 unused。
list(a) 而不是[x for x in a] 会快得多。我将list(a) 与上述选项一起计时(它非常快!),但我没有包括计时,因为它创建了一个包含所有结果的不需要的列表,在某些情况下可能需要大量内存。我只包含了立即将所有内容发送到 Orcus 的解决方案。
我已经开始使用可以在需要时重复使用的双端队列:
do_all = deque(maxlen=0).extend
然后我可以使用生成器表达式:
do_all(poly.draw() for poly in model.polys)
【讨论】:
for poly in model.polys: poly.draw()快,也不是更易读。你为什么用它? (使用你已经拥有的一些可迭代对象可能会稍微快一些,但是显式构造一个生成器只是为了以这种方式使用它对我来说似乎毫无意义。)
poly(必须防止对 for 循环体进行任何修改) .大多数for循环都没关系,但就我而言,我正在绘制许多,许多多边形。 (在fractallography.com查看我的作品)
你可以试试:
reduce(lambda _, __: None, chan)
但老实说,我认为你不会比普通循环做得更好。 “通道”表明 I/O 无论如何都会成为瓶颈。
【讨论】:
lambda 函数比纯 for 循环慢得多。