如何循环遍历生成器?我考虑了以下方法:
gen = function_that_returns_a_generator(param1, param2)
if gen: # in case the generator is null
while True:
try:
print gen.next()
except StopIteration:
break
有更Pythonic的方式吗?
简单地说
for x in gen:
# whatever
这将起到作用。请注意,if gen
的返回值总是 True
。
if gen
并不总是返回True
。如果操作中的function_that_returns_a_generator()
返回None
,那么在if
语句中,gen
会被解析为False
。 - drevickofunction_that_returns_a_generator()
返回一个生成器(这是一个大胆的假设,不是吗?)。None
不是一个生成器。 - Sven Marnach如果你只关心生成器的副作用而不需要它的输出,你可以使用以下一行代码:
for _ in gen: pass
在aiven的评论后,我进行了一些性能测试,虽然list(gen)
比for _ in gen: pass
稍微快一点,但是结果表明tuple(gen)
更快。然而,正如Erik Aronesty正确指出的那样,tuple(gen)
和list(gen)
都会存储结果,因此我的最终建议是使用
tuple(gen)
但前提是生成器不会循环数十亿次,以免占用过多内存。
list(gen)
来生成列表。 - aivenfor item in function_that_returns_a_generator(param1, param2):
print item
如果函数没有返回任何值,你不需要担心是否有任何返回值,因为如果没有返回值,你将不会进入循环。
>>> gen = (i for i in range(1, 4))
>>> for i in gen: print i
1
2
3
但请注意,您只能循环一次。下一次生成器将为空:
>>> for i in gen: print i
>>>
x = list(generator)
对于简单的预处理,使用列表推导式:
x = [tup[0] for tup in generator]
如果您只想执行生成器而不保存结果,可以跳过变量赋值:
# no var assignment b/c we don't need what print() returns
[print(_) for _ in gen]
list(generator)
正是我所需要的。 - Mike把它当作任何其他可迭代对象一样处理:
for val in function_that_returns_a_generator(p1, p2):
print val
if gen:
将始终为真,因此这是一个错误的测试。 from pdb import set_trace
for x in gen:
set_trace()
#do whatever you want with x at the command prompt
#use pdb commands to step through each loop of the generator e.g., >>c #continue
[None]*1000
的列表,你可以这样做:>>> d = {} # just a test-case scenario
>>> iterate = lambda *args: None # still invokes GC on (None)*1000
>>> iterate( *(d.__setitem__(k,None) for k in 'ABCDE') )
>>> d
{'A': None, 'D': None, 'C': None, 'B': None, 'E': None}
只是为了提供背景,展示被抓取的对象:
>>> d = {}
>>> iterate = lambda *args: print(args)
>>> iterate( *(d.__setitem__(k,None) for k in 'ABCDE') )
(None, None, None, None, None)
>>> d
{'A': None, 'D': None, 'C': None, 'B': None, 'E': None}
break
而不是continue
。 - Jon Clementsgen.__next__()
。 - Jann Poppinga