这是一个关于Python内部的问题。以下代码摘自这个关于蟒蛇懒惰的视频
def nats(n):
yield n
yield from nats(n + 1)
def sieve(s):
n = next(s)
yield n
yield from sieve(i for i in s if i % n != 0)
s = sieve(nats(2))
print(next(s), next(s), next(s), next(s), next(s)) # Primes: 2, 3, 5, 7, 11...筛子函数懒洋洋地生成素数(原始概念读入这 )。在概念上,我们将过滤器添加到“筛子”中,因此每个数字(例如,10)都会根据所有先前发现的素数(so 2、3、5和7)进行测试,直到找到下一个素数为止,即11.11随后被添加到过滤器的“列表”中,等等。
这一部分(i for i in s if i % n != 0)是一个生成器表达式(或“理解”)。
我的问题涉及Python用来“嵌套”这些生成器表达式的机制。例如,让我们使用两个可能的遍历表达式:
当我们第一次浏览它时,我们使用nats (用于自然数),并在其中添加2过滤器。
第二次,我们使用已经“经过”nats和2 filter的生成器,并在其中添加3过滤器。我们的收益来自[3,2,nats],后者来自[2,nats],后者来自[nats]。要点是,在每一层传递时,都需要保留变量的上下文,例如,每一层都“看到”不同的n。
但是Python到底在这里做什么呢?以下是一些我认为是可能的选择:
i % 2 != 0 and i % 3 != 0 and i % 4 !=0。或者也许我错过了一些关于这里发生的事情的基本内容?
发布于 2021-08-14 20:34:15
FWIW,您可以通过删除递归并在生成器内使用一个循环来避免堆栈溢出。这会让你产生更大的素数,但这不是免费的午餐。您仍然通过捕获所有生成器对象来消耗内存,而不是通过递归来完成。它将逐渐变慢,最终耗尽资源:
def nats(n):
while True:
yield n
n += 1
def sieve(s):
while True:
n = next(s)
yield n
s = filter(lambda i, n=n: i % n != 0, s)
s = sieve(nats(2))
# generate the 3000th prime
for x in range(3000):
n = next(s)
print(n)
# 27449https://stackoverflow.com/questions/68786282
复制相似问题