3 回答
TA贡献2039条经验 获得超8个赞
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。因此,计算要产生的值L24%3!=0is 评估为Truesoprime=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)
添加回答
举报
