Python递归函数与生成器的应用
一、递归的基本概念
在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