不循环排水或丢弃发电机?
解决方法:使用`collections.deque()`方法来处理生成器,可以更快速地处理。具体的代码如下:
collections.deque(chan, maxlen=0)
原因:根据测试结果来看,使用`collections.deque()`方法相比其他方法更快。具体的测试结果如下:
import collections a = range(100000) # 使用reduce方法 %timeit reduce(lambda _, __: None, a) # 13.5 ms per loop # 使用for循环 %timeit for dummy in a: pass # 1.75 ms per loop # 使用collections.deque()方法 %timeit collections.deque(a, maxlen=0) # 1.51 ms per loop
此外,还有关于使用下划线`_`作为变量名的讨论。在Python中,使用下划线作为变量名没有特殊的含义,但是它容易与Python交互式环境中的下划线(表示上一个表达式的结果)和常用的`gettext`别名发生冲突。因此,建议使用其他变量名,如`dummy`或`unused`。在其他语言中,下划线可能有特殊的含义,但在Python中没有。虽然在一些情况下,使用下划线作为变量名是常见的,但并没有明确的约定或优势,所以最好避免使用。此外,使用其他更具描述性的变量名可以提高代码的可读性。
另外,还有使用`list(a)`方法来处理生成器的方式,这种方法更加快速,但会在某些情况下占用大量内存。因此,作者没有将该方法包含在测试中。
最后,还提到了`collections.deque()`方法在C语言实现中进行了手动优化,可以更高效地处理生成器。具体的C语言实现代码可以在github.com/python/cpython/blob/…上找到。
在这段对话中,问题的出现是因为作者想要了解如何在不使用循环的情况下处理或丢弃一个生成器。解决方法是使用deque
数据结构和do_all
函数来消耗生成器表达式。
作者开始使用了一个可以重复使用的deque
:
do_all = deque(maxlen=0).extend
然后使用以下方式消耗生成器表达式:
do_all(poly.draw() for poly in model.polys)
但是这种方法并不比for poly in model.polys: poly.draw()
更快,也不更可读。作者询问为什么要使用这种方法,因为明确构造一个生成器只是为了这样消耗它似乎是毫无意义的。
问题的提出者问作者的评论是基于实际测试还是凭感觉。作者表示已经进行了一些测试,发现这种方法可以提高大约5%的性能,因为do_all
在C中进行迭代,而不是在Python中迭代变量poly
(在for循环体中必须防止对其进行任何修改)。大多数情况下,这并不重要,但在作者的情况下,他要绘制非常多的多边形。
作者表示这些测试是基于实际测试的,并提供了一些最基本的测试结果。他还提到了itertools
模块,并表示会再次查看Raymond Hettinger关于该模块的讲解。感谢提问者对他的监督。