从现在开始,对 Python 的讲解慢慢进入深水区,有什么不理解的,可以在评论区留言询问。
在 Python 中,生成器是一种生成迭代器的方便的方法,可以通过实现生成器函数实现的。生成器函数和普通函数类似,唯一的不同点是,生成器函数使用 yield
语句返回,而不是 return
语句。生成器函数中也可以包含 return
语句,但是 return
语句不是用来返回迭代器的。
根据定义,如果一个函数中至少有一个 yield
语句,那么它就是一个生成函数。使用 yield
语句的主要区别在于,它会暂停函数并保存其内部状态,当下次调用函数时,它会从上次 yield
的行开始。这种设计模式使迭代器功能变得简单而高效。
在内部,__iter__
和 __next__
等方法是自动实现的,StopIteration
异常也是自动引发的。本地属性及其值在连续调用之间被保留,开发者无需执行额外的逻辑。每当 Python 解释器识别到一个生成器函数(包含 yield
语句的函数)时,它就会提供所有这些功能。
为了了解生成器的工作原理,我们将从一个简单的生成器示例开始,该示例用于生成字母表前三个字母的序列:
def 天干迭代器的生成器():
yield '甲'
yield '乙'
yield '丙'
yield '丁'
yield '戊'
yield '己'
yield '庚'
yield '辛'
yield '壬'
yield '癸'
if __name__ == '__main__':
iter1 = 天干迭代器的生成器()
iter2 = 天干迭代器的生成器()
print(iter1.__next__())
print(next(iter1))
print(iter2.__next__())
print(next(iter2))
在这个例子中,我们使用 yield
语句实现了一个生成器。在主程序中,我们做了以下事情:
天干迭代器的生成器
函数,获取了两个迭代器,iter1
和 iter2
;__next__
方法,输出一个天干;next
函数,输出下一个天干。以上代码的输出结果是:
甲
乙
甲
乙
接下来,我们修订 星期类
类,不再单独定义一个迭代器类,而是使用生器生成迭代器。修订后的代码如下:
class 星期类:
def __init__(我):
我.星期字典 = {1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', 7: '星期日'}
def 星期迭代器生成器(我):
for key in 我.星期字典:
yield 我.星期字典[key]
if __name__ == '__main__':
星期 = 星期类()
iter1 = 星期.星期迭代器生成器()
iter2 = 星期.星期迭代器生成器()
print(iter1.__next__())
print(iter2.__next__())
print(next(iter1))
print(next(iter2))
相比之前的代码,这个用生成器生成迭代器的代码,简洁多了。接下来,我们讲解一下生成器的几个关键特性。
生成器表达式可用于动态创建简单的生成器(也称为匿名函数),而无需编写特殊的方法。语法类似于列表推导式,只是我们使用圆括号而不是方括号。下一个代码示例展示了如何使用生成器表达式创建生成器、它的用法,以及与列表推导式的比较:
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#推导式,每个元素加一
f1 = [x + 1 for x in L]
#生成器
g1 = (x + 1 for x in L)
print(f1)
print(g1.__next__())
print(g1.__next__())
print(next(g1))
print(next(g1))
输出结果是:
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
2
3
4
5
生成器还可以用来实现数据的无限流。一直以来,把无限流数据放入内存都是一个挑站,这个问题可以用生成器很方便地解决,因为迭代器一次只加载一项数据。下面是一个计算斐波那契数列的例子:
def 斐波那契数列():
n, a, b = 0, 0, 1
while True:
yield a
a, b = b, a + b
n += 1
if __name__ == '__main__':
iter = 斐波那契数列()
print(next(iter))
print(next(iter))
print(next(iter))
print(next(iter))
print(next(iter))
print(next(iter))
在处理复杂问题时,可以把多个生成器做成流水线,以实现任何目标。我们可以用一个例子来解释把多个生成器做成流水线的概念。我们要解决的问题是求质数的平方和。这个问题可以通过传统的 for
循环来解决,但我们将尝试使用两个生成器来解决这个问题:质数生成器
生成器用于生成质数,平方生成器
生成器用于求出由 质数生成器
生成器送入该生成器的质数的平方。我们将这两个生成器做成流水线输入求和函数,以得到所需的结果。以下是解决问题的代码:
def 是质数(数字):
for i in range(2, 数字):
if (数字 % i == 0):
return False
return True
def 质数生成器(num):
for c in range(2, num + 1 ):
if(是质数(c)):
yield c
def 平方生成器(质数列表):
for 质数 in 质数列表:
yield 质数 * 质数
if __name__ == '__main__':
iter1 = 平方生成器(质数生成器(5))
print(next(iter1))
print(next(iter1))
print(next(iter1))
print(sum(平方生成器(质数生成器(5))))
以上代码的输出结果是:
4
9
25
38
生成器是按需运行的,因此不仅内存效率高 还提供了一种在需要时生成值的方法。这有助于避免 不必要的数据生成,因为这些数据可能根本用不上。生成器非常适合 生成器非常适合用于大量数据处理、将数据从一个函数传输到其他函数,以及模拟并行计算。以及模拟并发。
<完>