在生成器中使用continue
我想用continue这个功能来跳过一些不符合特定条件的生成项。
如果我直接打印x
,我会得到完整的输出:
>>> w = [1,4,6,10]
>>> w2 = ((2 * x) for x in w)
>>> for x in w2: print x
...
2
8
12
20
但是,当我试图用continue
来不打印8的时候,输出却变成了空白。
>>> for x in w2:
... if x == 8: continue
... print x
...
>>>
我想在第二次循环中得到2、12和20的输出。我该怎么做才能得到想要的结果呢?
2 个回答
1
>>> w=[1,4,6,10]
>>> w2=((2 * x) for x in w)
>>> for x in w2:
... print x
...
2
8
12
20
>>> w2=((2 * x) for x in w)
>>> for x in w2:
... if x == 8: continue
... print x
...
2
12
20
给出正确的结果?!
你每次在使用 for 循环之前,都需要用 w2=((2 * x) for x in w)
这段代码(如果你是在终端上,就像 enrico.bacis 说的那样)。最好还是使用一个集成开发环境(IDE),像 IDLE 也可以。如果你还是想用命令行,那就最好写一个 function
。
2
生成器和列表不一样,生成器是在需要的时候才生成元素,而且这些元素不会一直保存在内存里。一旦你把所有的元素都用完了,再次尝试遍历它们时,生成器就不会再输出任何东西,因为它已经被用过了。
很可能你在第一次循环中就已经用掉了生成器,所以当你再尝试遍历它时,它是空的。你可以试着用 print list(w2)
来检查一下你的元素是否还在。
示例
我们来定义一个函数,从一个可迭代对象中打印元素,直到遇到某个值:
def printuntil(iterable, stopval):
for item in iterable:
print item
if item == stopval:
break
现在我们用一个列表试两次:
>>> vals = [2 * x for x in range(3)]
>>> printuntil(vals, 2)
0
2
>>> printuntil(vals, 4)
0
2
4
一切看起来都没问题,我们再用生成器试一次:
>>> vals = (2 * x for x in range(3))
>>> printuntil(vals, 2)
0
2
>>> printuntil(vals, 4)
4
如你所见,数字 0
和 2
已经被用掉了,所以第二次调用只打印了第一个还没被用掉的元素:4
。所以如果你想多次遍历一个可迭代对象,最好用列表。
复制生成器
你可以在使用生成器之前用 itertools.tee
来复制它,这样就能享受到不把元素存到列表里的好处。
>>> vals = (2 * x for x in range(5))
>>> from itertools import tee
>>> vals, valscopy = tee(vals)
>>> printuntil(vals, 2)
0
2
>>> printuntil(valscopy, 4)
0
2
4
这样做会节省内存,但在性能上可能不太高效,因为每次都需要生成元素。