3 回答
TA贡献2039条经验 获得超7个赞
def sieve_primes(stop=10):
L = (x for x in range(2, stop+1))
while True:
prime = next(L)
L = filter(lambda x: x % prime != 0 or x == prime, L)
yield prime
您的代码中到底发生了什么在下面逐次迭代中给出。为方便起见,我在第一次迭代中将 L 表示为 L1,在第二次迭代中将 L 表示为 L2,依此类推。
在第一次迭代
prime=next(L)
中为 2(如预期的那样)。L1=filter(lambda x: x % prime != 0 or x == prime, L)
(的值L
是惰性计算的,即仅根据需要计算的值。yield prime
将产生2
预期的结果。在第二次迭代
prime=next(L1)
中。棘手的部分来了。L1
是filter object
其值仅按需计算。因此,在第二次迭代中,当prime=next(L1)
执行时,仅计算一个值L
。现在 lambda 使用 prime as2
并计算一个值,即3
(3%2!=0
) ,即 nowprime
。L2=filter(lambda x: x % prime != 0 or x == prime, L1)
(的值L2
是惰性计算的,即仅按需计算的值。现在您yield prime
将屈服3
。在第三次迭代
prime=next(L2)
中。现在事情变得有点复杂了。要从中获得一个值,L2
您需要计算一个值,L1
而要计算一个值L1
,您需要计算一个值L
。如果你没记错的话L
,现在将 yield4
它将被用于L1
产生一个值。但最新的参考prime
是3
.4%3!=0
被评估为True
。所以,L1
产量4
。因此,计算要产生的值L2
4%3!=0
is 评估为True
soprime=next(L2)
is4
。
对进一步的迭代应用相同的逻辑,您会发现 5,6,7,8,9... 将在进一步的迭代中产生。
TA贡献1789条经验 获得超8个赞
您prime
在 lambda 中使用变量,这是您从封闭范围继承的引用。当您的代码评估 lambda 时,它将使用在继承引用的范围内绑定到该引用的任何值。当您不使用tee
和评估列表时,所有 lambda 函数都是相同的,并且对prime
.
tee
工作原理是将结果存储在一个列表中,并在您稍后再次询问时从该列表中将它们提供给您,因此对于它的每个值prime
实际上将过滤器应用于来自的所有值L
prime
您可以通过在 的范围内绑定来解决此问题,方法lambda
是将其作为具有默认值的参数传递。这将该值保存为函数对象的一部分,prime
然后引用是对该存储值的本地引用。
TA贡献1799条经验 获得超9个赞
def sieve_primes(stop=10):
L = (x for x in range(2, stop+1))
while True:
prime = next(L)
L = filter(lambda x: x % prime != 0 or x == prime, L)
yield prime下面的呢?使用生成器表达式通常比使用 map/filter/reduce 更好。
#!/usr/bin/env python3
def sieve_primes(stop=100):
primes = []
for candidate in range(2, stop+1):
if not any(candidate % prime == 0 for prime in primes):
primes.append(candidate)
yield candidate
for prime in sieve_primes():
print(prime)
添加回答
举报