Python递归函数相关

Posted aquish

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python递归函数相关相关的知识,希望对你有一定的参考价值。

  函数中调用其他函数是解决实际问题中常用方法,递归函数便是函数在运行过程中调用自身的函数。它像是循环的另一种表达方式,不过相较于写循环,递归函数封装性较好、可读性较强。在解决一些循环问题时,使用递归函数往往更简洁有效。以往提到递归函数时,理解仅仅到它比循环更简洁。今天读了博主程序员的人生A的博客后,学习到递归函数的调用机制以及通过尾递归优化解决栈溢出的问题,特留随笔,作温习记录用。

  首先递归函数的调用是通过栈(stack)这一种数据结构实现,每多一次函数调用/返回,栈就增加/减少一层栈帧。既然提到它,不妨大致复习一下堆栈的相关。提栈就不得不提它的两个操作及一个性质:入栈(PUSH)和出栈(POP),他们按照先入后出、后入先出的顺序操作。进栈出栈就像往一个盒子里取放东西,先放的被后放的压在下面,要想取到下面的,自然要先拿出在上面的。栈之所以于程序有着至关重要的作用,是因为栈保存了一个程序调用时所需的维护信息,称为堆栈帧或活动记录。它一般包含几部分:1、函数的返回地址和参数;2、临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。堆栈的实质是一种运算受限于一端的线性表。那既然是线性表,大小自然是有限的。因此,当递归函数调用次数过大(即参数过大时),便会出现“栈溢出”的现象。

技术图片

  解决“栈溢出”的方法则是“尾递归优化”。尾递归是指在函数返回的时候,调用自身且return语句中不能包含表达式。这样编译器就可以把尾递归做优化,使递归本身无论被调用多少次,都只占用一个栈帧,这样便不会出现栈溢出的情况。

用最简单的阶乘函数举例。

使用循环计算1*2*3*...*n: 

n = int(input("输出一个数:"))
if n == 0:
sum = 0
else:
sum = 1
for i in range(1,n+1):
sum *= i
print("它的阶乘为:",sum)

使用递归函数计算:
def recursion(n):
if n==1:
return 1
return n * recursion(n - 1)
a = int(input("输入一个数:"))
print("它的阶乘为:", recursion(a))
但当a过大时,编译器便会因栈溢出而报错,这是就需要用到尾递归优化。

尾递归优化:
def recursion(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
优化后,函数仅返回递归函数本身,这样栈帧中数据每一次使用后更新,栈不再增长,无论调用多少次都不会导致栈溢出。遗憾的是python解释器并没有针对尾递归做优化,因此用python时即使进行了尾递归优化,还是会导致栈溢出。

 

以上是关于Python递归函数相关的主要内容,如果未能解决你的问题,请参考以下文章

python3--函数(函数,全局变量和局部变量,递归函数)

如何在自定义PyYAML构造函数中处理递归?

python函数(全局变量,局部变量,作用域,递归函数,高阶函数,匿名函数)

python之内置函数与匿名函数递归函数初识

python函数:递归函数及二分查找算法

python递归函数