首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python生成器表达式递归

Python生成器表达式递归
EN

Stack Overflow用户
提问于 2021-08-14 19:06:16
回答 3查看 155关注 0票数 0

这是一个关于Python内部的问题。以下代码摘自这个关于蟒蛇懒惰的视频

代码语言:javascript
运行
复制
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过滤器

第二次,我们使用已经“经过”nats2 filter的生成器,并在其中添加3过滤器。我们的收益来自[3,2,nats],后者来自[2,nats],后者来自[nats]。要点是,在每一层传递时,都需要保留变量的上下文,例如,每一层都“看到”不同的n

但是Python到底在这里做什么呢?以下是一些我认为是可能的选择:

  1. 它是否为每个嵌套的生成器调用添加了堆栈框架?
  2. 它只需要创建一个闭包对象吗?
  3. 也许python将生成器“压缩”成一个类似于以下表达式的生成器:i % 2 != 0 and i % 3 != 0 and i % 4 !=0

或者也许我错过了一些关于这里发生的事情的基本内容?

EN

Stack Overflow用户

发布于 2021-08-14 20:34:15

FWIW,您可以通过删除递归并在生成器内使用一个循环来避免堆栈溢出。这会让你产生更大的素数,但这不是免费的午餐。您仍然通过捕获所有生成器对象来消耗内存,而不是通过递归来完成。它将逐渐变慢,最终耗尽资源:

代码语言:javascript
运行
复制
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)
# 27449
票数 1
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68786282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档