当前位置:首页 > 技术 > 正文内容

Python递归函数与生成器的应用

访客 技术 2026年7月2日 1

一、递归的基本概念

在Python中,如果一个函数内部直接或者间接地调用了自身,我们就称这个函数为递归函数。递归是一种非常强大的编程技巧,它通过将复杂的问题分解为与原问题结构相同的子问题来求解。使用递归可以让代码更加简洁优雅,尤其是在处理具有自相似结构的问题时。

举一个具体的例子:计算1到n的连续乘积(阶乘)。如果用普通循环来实现,当n非常大时代码会变得冗长;而使用递归则可以轻松完成这个任务:

1 def multiply(n):
2     if n <= 1:
3         return 1
4     return n * multiply(n - 1)
5 
6 print(multiply(6))

运行结果:720

接下来观察递归的实际执行流程:

1 def process(num):
2     print(num)
3     if num / 2 > 1:
4         result = process(num / 2)
5     return num
6 
7 process(10)

输出结果:

1 10
2 5.0
3 2.5

再来看一个能展示调用栈的示例:

1 def process(num):
2     print(num)
3     if num / 2 > 1:
4         result = process(num / 2)
5         print('result:', result)
6     print("当前值:", num)
7     return num
8 
9 process(10)

输出结果:

1 10
2 5.0
3 2.5
4 当前值: 2.5
5 result: 2.5
6 当前值: 5.0
7 result: 5.0
8 当前值: 10

二、生成器的使用

生成器是Python中一种特殊的迭代器,它通过yield关键字来产生值。与普通函数只返回一次不同,生成器可以在产生值之后暂停执行,保存当前状态,等待下一次调用时继续执行。这种特性使得生成器非常适合处理大数据流或无限序列。

请看下面的示例:

1 def sequence():
2     print('第一次执行')
3     yield [1, 2]
4     print('第二次执行')
5     yield 100
6     print('第三次执行')
7     yield 200
8 
9 obj = sequence()
10 val1 = obj.__next__()
11 print(val1)
12 val2 = obj.__next__()
13 print(val2)
14 val3 = obj.__next__()
15 print(val3)

输出结果:

1 第一次执行
2 [1, 2]
3 第二次执行
4 100
5 第三次执行
6 200

虽然可以直接调用__next__方法,但Python的for循环对迭代器有很好的支持,使用for循环遍历生成器会更加简洁:

1 def sequence():
2     print('第一步')
3     yield [1, 2]
4     print('第二步')
5     yield 100
6     print('第三步')
7     yield 200
8 
9 obj = sequence()
10 for item in obj:
11     print(item)

运行结果与上面相同。

生成器还提供了几个高级特性:通过send()方法向生成器内部发送数据、通过throw()方法抛出异常、以及通过close()方法关闭生成器。下面是一个综合示例:

1 def number_sequence(start=0):
2     count = start
3     while True:
4         received = yield count
5         if received is not None:
6             count = received
7         else:
8             count += 1

这个生成器维护一个计数器,默认从0开始递增。用户既可以直接调用next()让计数器自动递增,也可以使用send()方法重置计数器的值。调用close()方法可以停止生成器:

1 >>> nums = number_sequence(5)
2 >>> next(nums)
3 5
4 >>> next(nums)
5 6
6 >>> nums.send(9)
7 9
8 >>> next(nums)
9 10
10 >>> nums.close()
11 >>> next(nums)
12 Traceback (most recent call last):
13   File "<stdin>", line 1, in <module>
14 StopIteration

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。