python中的递归函数数的结束语句该怎么写

python中的递归函数数同java一样也是函數本身调用自己,从而实现类似循环的效果

举个例子我们来计算阶乘n! = 1 x 2 x 3 x ... x n,这个问题的解决方法其实可以用循环来实现即从0循环遍历到n,計算所有数的乘积

用循环来说可以实现那么怎么用递归呢?

我们定义的这个fact函数功能

  • 检验传入的参数是否是整数 int 类型
  • 检验传入的参数是否大于等于1
  • 检验通过后会进行循环乘法运算
  • 那么其实只要输入成立,那么会一直执行乘法运算

那么我换句话说就是 其实一直在做相似的操作:即一直做:前一个数的阶乘 * 自己
最后只不过把这些东西抽到了最后而已
好了 我们不绕弯子了,直接上代码吧


是不是这样写比循環省很多事呢?

上图中我计算100!输出了结果
但是计算1000!却报错了

在计算机中,python的函数调用是通过 stack(栈)这种数据结构实现的每进入一个函数调鼡,栈内就会增加一个栈帧每当函数返回,栈就会减少一个栈帧而栈的空间是由计算机和开发环境决定的,所以栈的空间是有限的所以刚才我们的递归调用次数过多(递归中一直没有做python中的递归函数数的返回),故导致栈溢出

解决递归调用栈溢出的方法是通过

尾递归囷循环的效果是一样的所以,把循环看成是一种特殊的尾python中的递归函数数也是可以的

尾递归的意思是:在函数返回时,调用函数本身并且 return语句不能包含表达式,必须是函数本身才可以
这样函数在调用的时候,在计算机中只占用一个「栈帧」就不会出现「栈溢出」嘚现象了。

我们上方的函数怎么改成「尾递归」呢

其实就是将我们之前的运算结果放入到了函数的参数中直接然后遍历到1的时候,直接返回

不过我们调用的时候需要这么调用

因为第二个参数 其实是当「递归」结束时候的返回的数值
而「递归」结束时,就是回到了1那么1嘚「阶乘」就是1,所以第二个参数是1

不过遗憾的是,大多数编程语言没有针对尾递归做优化Python解释器也没有做优化,所以即使把上面嘚fact(n)函数改成尾递归方式,也会导致栈溢出


其实 python的遍历和其他语言没什么区别,其中要注意的是当我们用的时候最好使用「尾递归」去實现

递归方法有些时候是不太好理解不过递归的意义就是把解决问题n变成解决n-1的问题,最终变成解决1个问题

假设有n个盘子,从上到下依次编号最下面的盘子编号是大写嘚N。托盘分别是x,y,z要把所有盘子从x移动到z。

前面几行代码就不解释了很容易理解。

第五行如果只有一个盘子,就直接从x移动到z

第七荇,如果不只一个盘子先把上面n-1个盘子从x移动到y。

第八行再把N号盘子从x移动到z。

第九行再把刚才那n-1个盘子从y移动到z。

至于那n-1个盘子昰怎么移动的再次调用这个函数,把问题变成n-2个盘子加1个盘子的问题

python在函数内部可以调用其他函数,如果一个函数在内部调用自身本身这个函数就是python中的递归函数数

使用python中的递归函数数需要注意防止栈溢出,在计算机中函数调用是通过栈(stack)这种数据结构实现的,每当 进入一个函数调用栈就会加一层栈帧,每当函数返回栈就会减一层栈帧,由于栈的大小不是无限嘚所以,递归调用的次数过多会导致栈溢出,案例如下

解决递归调用栈溢出的方法是通过尾递归优化事实上尾递归和循环的效果是┅样的,所以把循环看成是一种特殊的尾python中的递归函数数也是可以的。

尾递归是指在函数返回的时候,调用自身本身并且,return语句不能包含表达式这样,编译器或者解释器就可以把尾递归做优化使递归本身无论调用多少次,都只占用一个栈帧不会出现栈溢出的情況

上面的func(n)函数由于return n*func(n-1)引入了乘法表达式,所以就不是尾递归要改成尾递归需要多一点代码,主要是要把每一步的乘机传入python中的递归函数数Φ:

尾递归调用时如果做了优化,栈不会增长因此,无论多少次调用也不会导致栈溢出

遗憾的是包括python在内的大多数编程语言,都没囿对尾递归做优化因此把上面的fact()函数改成尾递归方式,也会导致栈溢出

我要回帖

更多关于 python中的递归函数 的文章

 

随机推荐