Python 用生成器定义“fac”。还有:为什么发电机没有堆栈溢出?
有没有办法通过Python中的生成器定义以下代码(递归的经典示例)?我正在使用Python3Python 用生成器定义“fac”。还有:为什么发电机没有堆栈溢出?,python,Python,有没有办法通过Python中的生成器定义以下代码(递归的经典示例)?我正在使用Python3 def fac(n): 如果n==0: 返回1 其他: 返回n*fac(n-1) 我试过了,没有成功: [1]中的:定义fib(n): …:如果n==0: …:收益率1 …:其他: …:n*产量(n-1) 文件“”,第5行 n*产量(n-1) ^ SyntaxError:无效语法 Python中的经典递归导致堆栈溢出 这个经典示例导致我的机器上的堆栈溢出,输入值为n=3000。在Lisp方言“Sch
def fac(n):
如果n==0:
返回1
其他:
返回n*fac(n-1)
我试过了,没有成功:
[1]中的:定义fib(n):
…:如果n==0:
…:收益率1
…:其他:
…:n*产量(n-1)
文件“”,第5行
n*产量(n-1)
^
SyntaxError:无效语法
Python中的经典递归导致堆栈溢出
这个经典示例导致我的机器上的堆栈溢出,输入值为n=3000
。在Lisp方言“Scheme”中,我将使用尾部递归并避免堆栈溢出。在Python中不可能。这就是为什么生成器在Python中派上用场的原因。但我想知道:
为什么发电机没有堆栈溢出?
为什么Python中的生成器没有堆栈溢出?他们如何在内部工作?做了一些研究之后,我总是会看到一些示例,展示如何在Python中使用生成器,但并没有太多关于内部工作的内容
更新1:从my_函数中获得收益(…)
正如我试图在评论中解释的那样,也许我上面的例子是一个错误的选择。我的实际问题是针对Python 3中yield from
语句中递归使用的生成器的内部工作
下面是我用来处理Firebox书签备份生成的JSON文件的(不完整)示例代码。在某些情况下,我使用yield from process_json(…)
通过生成器再次递归调用函数
在本例中,如何避免堆栈溢出?还是这样
#(剪报)
文件夹和书签={}
文件夹\u日期={}
def process_json(json_输入,文件夹_路径=”):
全局文件夹\u和\u书签
#使用生成器处理json
#(为了避免递归,请使用生成器)
# https://stackoverflow.com/a/39016088/5115219
#node是dict吗?
如果isinstance(json_输入,dict):
#我们有一个口述
guid=json_输入['guid']
title=json_输入['title']
idx=json_输入['index']
date_added=到_datetime_applescript(json_输入['dateAdded'])
last_modified=to_datetime_applescript(json_输入['lastModified'])
#我们有容器还是书签?
#
#字典里有“uri”吗?
#如果没有,我们有一个容器
如果json_input.keys()中的“uri”:
uri=json_输入['uri']
#返回带有文件夹或容器的URL(=上一个标题)
#书签=[guid、标题、idx、uri、添加日期、上次修改]
书签={'title':标题,
'uri':uri,
“添加日期”:添加日期,
“上次修改”:上次修改}
文件夹和书签[文件夹路径].附加(书签)
收益书签
json_input.keys()中的elif“children”:
#所以我们有一个容器(又名文件夹)。
#
#创建一个新文件夹
如果标题!=“”:#我们不是根
文件夹路径=f“{folder\u path}/{title}”
如果文件夹和书签中的文件夹路径为:
通过
其他:
文件夹和书签[文件夹路径]=[]
文件夹日期[文件夹路径]={'date'u added':date'u added','last'u modified':last'u modified}
#在子进程列表上运行进程\u json
#json_输入['children']:目录列表
从进程生成json(json输入['children'],文件夹路径)
#或者节点是一个目录列表?
elif isinstance(json_输入,列表):
#处理容器的子级。
dict_list=json_输入
对于dict_列表中的d:
来自进程\u json(d,文件夹\u路径)的产量
更新2:yield
vsyield from
好的,我明白了。感谢所有的评论
- 因此,通过
迭代器。这与递归无关,因此这里没有堆栈溢出生成的生成器将生成
- 但是,通过
生成的生成器实际上是我函数的递归调用,尽管有延迟,并且只有在需要时才进行计算李>从my_函数(…)
第二个示例确实会导致堆栈溢出 好的,在你的评论之后,我已经完全重写了我的答案
def fac(n):
if (n <= 0):
yield 1
else:
v = 1
for i in range(1, n+1):
v = v * i
yield v
这看起来是递归的,但它是两个生成器对象的组合。您拥有“内部”生成器(仅使用一个对象的空间),使用yield from
您可以说“我想将该生成器中的所有值转发给我的调用者”
所以
def process_json(json_input, folder_path=""):
# Some code
yield from process_json(json_input['children'], folder_path)