Python进阶之尾递归的用法实例

yipeiwu_com5年前Python基础

作者是一名沉迷于Python无法自拔的蛇友,为提高水平,把Python的重点和有趣的实例发在简书上。

尾递归

如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。

(来源于不说人话的某度)

下面是笔者的个人理解:把计算出的值存在函数内部(当然不止尾递归)是其计算方法,从而不用在栈中去创建一个新的,这样就大大节省了空间。函数调用中最后返回的结果是单纯的递归函数调用(或返回结果)就是尾递归。

实例

实例还是和笔者的上一篇文章相同,建议读者阅读 Python —— 递归

1、阶乘

常规递归阶乘:

def factorial(n): 
  if n == 0:
    return 1
  return factorial(n - 1) * n

我们来看一下执行过程:

factorial(4) 
factorial(3) * 4 
factorial(2) * 3 * 4 
factorial(1) * 2 * 3 * 4 
factorial(0) * 1 * 2 * 3 * 4 
1 * 1 * 2 * 3 * 4 
1 * 2 * 3 * 4 
2 * 3 * 4 
6 * 4 
24

但是如果把上面的函数写成如下形式:

def factorial(n, acc=1): 
  if n == 0:
    return acc
  return factorial(n - 1, n * acc)

我们再看下执行过程:

factorial(4, 1) 
factorial(3, 4) 
factorial(2, 12) 
factorial(1, 24) 
factorial(0, 24) 
24

很直观的就可以看出,这次的 factorial 函数在递归调用的时候不会产生一系列逐渐增多的中间变量了,而是将状态保存在 acc 这个变量中。而这种形式的递归,就叫做尾递归。

2、斐波那契数列

常规递斐波那契数列:

def fib(n):
  if n < 2:
    return n
  else:
    return fib(n - 1) + fib(n - 2)

而尾递归:

def fib_tail(n, r, t):
  if n == 1:
    return r
  else:
    return fib_tail(n - 1, t, r + t)

一下子就充满了逼格,还高效了许多,何乐而不为呢!

总结

可以看出,在每次递归调用的时候,都会产生一个临时变量,导致进程内存占用量增大一些。这样执行一些递归层数比较深的代码时,除了无谓的内存浪费,还有可能导致著名的堆栈溢出错误。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

Python将文字转成语音并读出来的实例详解

Python将文字转成语音并读出来的实例详解

前言 本篇文章主要介绍,如何利用Python来实现将文字转成语音。将文字转成语音主要有两种不同的实现方法:先将文字转成语音,然后再通过读取语音实现发音、直接调用系统内置的语音引擎实现发音...

Python日期操作学习笔记

比如用 print ','.join(datelist) 就可以将datelist列表里面的所有项目并成一个字符串,当然这个表达式会在每一个项目中间插入一个逗号,这种方式比用循环的方式更...

python中文分词,使用结巴分词对python进行分词(实例讲解)

python中文分词,使用结巴分词对python进行分词(实例讲解)

在采集美女站时,需要对关键词进行分词,最终采用的是python的结巴分词方法。 中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词。 其基本实现原理有三点: 1.基于Tri...

用sqlalchemy构建Django连接池的实例

都知道django每次请求都会连接数据库和释放数据库连接。Django为每个请求使用新的数据库连接。一开始这个方法行得通。然而随着服务器上的负载的增加,创建/销毁连接数据库开始花大量的时...

Python模块future用法原理详解

这篇文章主要介绍了Python模块future用法原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 计算机的知识太多了,很多东西...