尾递归python
A. python的尾递归
原因很多人的都知道,让我们先回顾一下函数调用的大概过程:
1)调用开始前,调用方(或函数本身)会往栈上压相关的数据,参数,返回地址,局部变量等。
2)执行函数。
3)清理栈上相关的数据,返回。
因此,在函数 A 执行的时候,如果在第二步中,它又调用了另一个函数 B,B 又调用 C.... 栈就会不断地增长不断地装入数据,当这个调用链很深的时候,栈很容易就满 了,这就是一般递归函数所容易面临的大问题。
而尾递归在某些语言的实现上,能避免枯春上述所说的问题,注意是某些语言上,尾递归本身并不能蠢败扰消除函数调用栈过长的问题,那什么是尾递归呢?在上面写的一般递归函数 func() 中,我们可以看到,func(n) 是依赖于 func(n-1) 的,func(n) 只有在得到 func(n-1) 的结果之后,才能带旦计算它自己的返回值,因此理论上,在 func(n-1) 返回之前,func(n),不能结束返回。因此func(n)就必须保留它在栈上的数据,直到func(n-1)先返回,而尾递归的实现则可以在编译器的帮助下,消除这个限制
B. 如何看待以及理解Python的这种尾递归优化
TCO,tail-call optimization,其实有多种解读方式。
最常见的解读方式是:对于尾调用的函数调用,不要浪费栈空间,而要复用调用者的栈空间。这样的结果就是一长串尾调用不会爆栈,而没有TCO的话同样的调用就会爆栈。
从这个意义上说,题主贴的那个recipe确实达到了TCO的部分目的:
通过stack introspection查看调用链上的调用者之中有没有自己
有的话,通过抛异常来迫使栈回退(stack unwind)到之前的一个自己的frame
在回退到的frame接住异常,拿出后来调用的参数,用新参数再次调用自己
这样就可以让尾递归不爆栈。但这样做性能是没保证的…而且对于完全没递归过的一般尾调用也不起作用。
一种对TCO的常见误解是:由编雀宽译器或运行时系统把尾调用/尾递归实现得很快。这不是TCO真正要强调的事情——不爆栈慧誉才是最重要的。也就是说其实重点不在“优化”,而在于“顷碧亮尾调用不爆栈”这个语义保证。
“proper tail-call”的叫法远比“tail-call optimization”来得合适。
因而像题主说的那种做法,可以算部分TCO,但算不上“性能优化”意义上的优化。
C. scheme递归的优势在哪
python根祥燃本就没有尾递归,scheme却有,所以scheme更有效率
尾递归的优势,是可以迭代,程序消耗的内液棚存基本是恒定的
据我所知,尾递归不是大部分语言拥有的特性,C语言和lisp都谨埋虚用,连C++都没有,遑论其他语言了
chezscheme有很多优化选项,没开的话哪有优势?
尾递归,就是scheme相比python的一个绝对优势
D. python为什么不支持尾递归
Python本身是不支持尾递归的(via),并且对递归次数有限制的,当递归次数超过1000次的时候,就会册此芹抛州毕出“RuntimeError: maximum recursion depth exceeded”异常扒带。
E. 关于python递归函数怎样理解
递归的思想主要是能够重复某些动作,比如简单的阶乘,次方,回溯中的八皇后,数独,还有汉诺塔,分形。
由于堆栈的机制,一般的递归可以保留某些变量在历史状态中,比如你提到的return
x
*
power...,
但是某些或许庞大的问题或者是深度过大的问题就需要尽量避免递归,因为可能会栈溢出。还有一个问题是~python不支持尾递归优化!!!!所以~还是尽量避免递归的出现。
def
power(x,
n)
if
n
<
0:
return
1
return
x
*
power(x,
n
-
1)
power(3,
3)
3
*
power(3,
2)
3
*
(3
*
power(3,
1))
3
*
(3
*
(3
*
power(3,
0)))
3
*
(3
*
(3
*
1))
这里n
=
0,
return
1
3
*
(3
*
3)
3
*
9
27
当函数形参n=0的时候,开始回退~直到第一次调用power结束。
F. 如何理解python中的递归函数
递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。
绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。
计算机科学家尼克劳斯·维尔特如此描述递归:
递归的强大之处在于它允许用户用有限的语句描述无限的对象。因此,在计算机科学中,递归可以被用来描述无限步的运算,尽管描述运算的程序是有限的。
python 2 递归函数和其它语言,基本没有差别,只是不支持尾递归。无限递归最大值为固定的,但可以修改。
作者:黄哥
G. python,怎么使用递归的方法,提取括号中的字串符
当递归调用是整个函数体中滚伏中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。
尾递归函数的特点是在回归过程中不用做任何卖携操作,这个特性很重要,备竖因为大多数现代的编译器会利用这种特点自动生成优化的代码。
H. 如何看待以及理解Python的这种尾递归优化
把需要优化的函数的return改成yield,外面套个装辩唤饰器,就叫tail_call_opm。装饰器最内层的逻辑是
while True:
try:
ret=next(ret)
except:
return ret
这个应该没有复用释放的空间…但刷题时换了这个就不爆栈了侍灶或。返回闭包的话情况应该会更复杂一些。
不失为一个快速简单的办法老伍。
I. 很奇怪,为什么用Python的人喜欢递归呢
Python没有尾递归闹迅扮优化(按照常理应该没有,否则我只能觉得我所在的并非人间),就连Common Lisp都不要求这种优化,尽管很多Common Lisp实现都做这种优化或者提供pragma选昌梁项来打开这种优化,于是造成好像液灶是个Lisp就要支持尾递归优化一样。
J. 递归与伪递归区别,Python 实现递归与尾递归
(1)数据的定义是按递归定义的。(n的阶乘)
(2)问题解法按递归实现。(回溯)
(3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)