Python基础教程

第一章: 环境搭建,安装Python

第二章: 挑选一款趁手的IDE

第三章: 计算机基础知识

第四章: 命令行基础知识

第五章: 从全局把握Python

第六章: Python语言基础

第七章: Python流程控制

第八章: Python数据类型与运算

第九章: Python字符串类型

第十章: Python列表类型

第十一章: Python元组类型

第十二章: Python字典类型

第十三章: Python集合类型

第十四章: Python函数处理

第十五章: Python文件处理

第十六章: Python面向对象

第十七章: Python异常处理

第十八章: Python模块处理

第十九章: Python高级编程

第二十章: Python项目实战

首页 > Python基础教程 > 第十四章: Python函数处理 > 14.6节: 彻底掌握递归函数

14.6节: 彻底掌握递归函数

薯条老师 2020-05-22 16:30:21 232252 0

编辑 收藏

广州番禺Python, Java小班周末班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人,学员的平均就业薪资有11K。不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。培训的课程有Python爬虫,Python后端开发,Python办公自动化,Python大数据分析,Python量化投资,Python机器学习,Java中高级后端开发。授课详情请点击:https://my.pythoncn.com/?cate=6

14.6.1 理解递归函数

Python也支持定义递归函数。所谓的递归函数,是指自己调用自己的函数。这里的调用不一定是直接调用,也可以是间接地调用。

image.png

现在来举个简单的例子:

# __desc__ = 定义一个简单的递归函数
def recursive_sum(numbers): 
    # 在函数内部直接调用自己
    recursive_sum(numbers)
上文代码中定义的recursive_sum,就是一个递归函数。在函数recursive_sum内部,又继续调用了recursive_sum函数。在函数中如果调用自己,那么会形成一个调用环,递归函数的这种方式非常类似于循环结构。同学们可以通过下图进行理解:

image.png


在上文中定义的递归函数存在一个很严重的问题,它会不断地调用自己,消耗系统资源。将上文的代码实例在命令行中执行时,程序会异常终止:

# __desc__ = 定义一个简单的递归函数,并执行
def recursive_sum(numbers): 
    # 在函数内部直接调用自己
    recursive_sum(numbers)

# 调用该递归函数
recursive_sum([1,2,3,4,5])
执行该递归函数以后,Python会抛出递归错误的异常信息:
Traceback (most recent call last):
 File "demo.py", line 5, in <module>
   recursive_sum([1,2,3,4,5])
 File "demo.py", line 3, in recursive_sum
   recursive_sum(numbers)
 File "demo.py", line 3, in recursive_sum
   recursive_sum(numbers)
 File "demo.py", line 3, in recursive_sum
   recursive_sum(numbers)
 [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

在Python解释器的错误提示中,指示该递归函数已超出了最大递归深度。对于递归深度,同学们可以将其理解为递归函数的调用次数。

14.6.2 递归函数必须能够正常终止

在设计递归函数时,必须定义一个退出边界,否则函数会不断地递归执行,一旦超出Python语言所支持的递归深度,那么就会抛出RecursionError的错误异常。我们可以在函数体中使用控制语句加一段控制逻辑,当递归函数在条件不满足时就终止递归。所谓的终止递归,即不再调用自己。现在来写个简单的函数,逆序输出10到1之间的所有整数,使用递归函数进行实现:
# __desc__ = 定义递归函数,逆序输出10到1之间的所有整数
def count_backwards(number):
    # 当参数number大于0时,就输出number的值

    if number > 0:
        print(number)
        number -= 1
        # 不断调用自己,直到number小于等于0      
        count_backwards(number)
 
# 当参数number小于等于0时,函数将不再调用自己,此时会正常退出
 
# 执行这个递归函数
count_backwards(10)
 
""" 递归函数的输出为:
10
9
8
7
6
5
4
3
2
1
"""

14.6.3 在递归函数中返回值

递归函数较非递归函数,会更难理解,在熟练掌握了递归函数的用法以后,可以写出更加简洁的代码。现在来定义一个将列表进行求和的函数,使用非递归函数进行实现:
# __desc__ = 定义一个非递归函数,将列表进行求和
 
def accumulate(numbers):
    sum_of_numbers = 0
    for _ in numbers:
        sum_of_numbers += _
    return sum_of_numbers
 
sum_of_numbers = accumulate([1,2,3,4])
# sum_of_numbers的输出为10
定义一个将列表进行求和的函数,使用递归函数进行实现:
# __desc__ = 定义一个递归函数,将列表进行求和
 
def accumulate(numbers):
    # 递归版本只需一行代码即可实现
    return 0 if not numbers else numbers[-1]+accumulate(numbers[0:len(numbers)-1])
 
 
sum_of_numbers = accumulate([1,2,3,4])
# sum_of_numbers的输出为10
在上文的两则代码实例中,递归版的列表求和,只需要一行代码就实现了求和的功能。现在对这行代码进行详细地讲解:
(1) 该行代码最外层是一个三元运算结构:
return 0 if not numbers else numbers[-1]+accumulate(numbers[0:len(numbers)-1])
return 0 if not numbers
前面的这段代码表示,如果参数numbers为空,就返回0。
(2) 调用自己
else numbers[-1]+accumulate(numbers[0:len(numbers)-1])
后面的这段代码表示,如果列表numbers非空,那么就先取出列表最后一个元素:
numbers[-1]

然后对列表进行切片,再将切片后的列表作为参数传递给accumulate函数:
accumulate(numbers[0:

欢迎 你 发表评论: