我有以下循环重新分配给迭代器变量:
currentPrime = None
sieve = iter(range(2, 10))
while True:
try:
# The first value should be prime.
currentPrime = next(sieve)
except StopIteration:
# Stop when sieve is empty.
print(currentPrime)
break
print(currentPrime)
# Filter out all multiples of currentPrime.
sieve = (x for x in sieve if x % currentPrime)
#print(tuple(sieve))
即使我在循环的每次迭代中都应用了过滤器,输出也会遍历整个范围:
2
3
4
5
6
7
8
9
9
如果我取消对最后一个print
调用的注释,则会看到(3, 5, 7, 9)
,这意味着sieve
的过滤器和赋值工作正常,但是next(sieve)
调用以某种方式访问了原始没有变量指向的迭代器。
你知道这里发生了什么吗?我正在使用Python 3.7.0。
答案 0 :(得分:1)
正如user2357112所说,“ {currentPrime
是在使用时查找的,而不是在生成器时查找的。”
一种解决方案是将filter
与一个lambda一起使用,以对currentPrime
的当前值进行本地化。请注意lambda如何使用默认参数创建本地变量:
currentPrime = None
sieve = iter(range(2, 10))
while True:
try:
# The first value should be prime.
currentPrime = next(sieve)
except StopIteration:
# Stop when sieve is empty.
print(currentPrime)
break
# Filter out all multiples of currentPrime.
sieve = filter(lambda x, prime=currentPrime: x % prime, sieve)
答案 1 :(得分:0)
如果我没记错的话,有一堆发电机。
会发生什么(TL; DR:所有生成器都引用一个currentPrime实例,然后引用惰性):
从范围迭代器获取值2。
创建生成器表达式(A)。变量currentPrime = 2现在是 NOT 免费的(不是关闭的)。生成器消耗其余范围(3..9)。
从生成器A获取值3(3%2为True)
创建生成器表达式(B)。 两个发生器(A,B)的变量currentPrime = 3。发电机消耗发电机A的其余部分(4..9)。
从生成器B获取值4。请参见:next()→B.next(A)→A产生4(A检查:4% 3 为True),然后B检查4%3是正确的。
创建生成器表达式(C)...,依此类推。
生成器中的变量未关闭,请参见:
>>> a = 5
>>> gen = (a for i in range(3))
>>> a = 3
>>> list(gen)
[3, 3, 3]