生成器(Generator)
生成器(Generator)是Python中一种特殊的迭代器,它允许你在需要时才计算和产生值,而不是一次性生成整个序列。生成器使用yield语句来逐个产生值,而不是像迭代器那样实现__iter__()和__next__()方法。
- 生成器在需要的时候才产生结果,不是立即产生结果
- 生成器底层是使用迭代器来实现的
生成器有两种创建方式
- 使用生成器函数:通过包含yield关键字的函数来创建。
- 使用生成器表达式:类似于列表推导式,但是使用圆括号而不是方括号。将列表推导式中的
[]
替换为()
以下是一个使用生成器函数的例子:
# 定义一个生成器函数,用于生成斐波那契数列
def fibonacci_generator():first, second = 0, 1while True:yield first # 使用yield产生当前的斐波那契数,生成器first, second = second, first + second # 更新前两个斐波那契数# 创建生成器对象
fib_gen = fibonacci_generator()# 打印前10个斐波那契数
for i, value in enumerate(fib_gen):if i >= 10: # 打印前10个数后停止breakprint(i,value,sep="--")# 打印第10~25个斐波那契数
for i, value in enumerate(fib_gen):if 9 > i:continueelif i >= 26: # 打印后停止breakprint(i,value,sep="--")
上面代码的解释:
- fibonacci_generator是一个生成器函数,它使用yield关键字逐个产生斐波那契数。
- 在函数内部,first和second变量用于追踪当前的两个斐波那契数。
- yield first语句产生当前的斐波那契数,并保存函数的状态,这样在下一次调用next(fib_gen)时,函数可以继续执行。
- for循环使用enumerate来遍历生成器产生的值,并打印前10个斐波那契数。
生成器的另一个优点是它们是惰性的,这意味着它们在每次迭代时才计算值,这对于处理大数据集或无限序列非常有用,因为它们不需要预先分配内存来存储所有数据。
以下是一个使用生成器表达式的例子:
# 使用生成器表达式计算平方数
squares = (x**2 for x in range(10)) # 生成器表达式# 打印生成的平方数
for square in squares:print(square)
在这个例子中,生成器表达式(x**2 for x in range(10))创建了一个生成器,它会逐个产生0到9的平方数。当for循环遍历这个生成器时,它将逐个打印出这些平方数。
生成器实例
再一个例子:需要生成1000万条数据的列表
# 这种for循环方式产生列表是直接产生结果,生成结果需要时间最长。数据量大容易造成内存溢出。
from time import time
my_list = []
a = time()
for i in range(100000000):my_list.append(i)
# 先注释掉
# my_list
b = time()
print(b-a)
# 这种迭代器产生列表的方式是直接产生结果,生成也需要时间。
a = time()
my_list2 = [i for i in range(100000000)]
b = time()
print(b-a)
# 用生成器方式产生列表,需要时间
a = time()
gen = (i for i in range(100000000))
my_turple = iter( range(100000000) )
b = time()
print(b-a)
# 访问生成器,注意:与迭代器一样,生成器调用完就丢掉。
# 第一次调用__next__()方法就相当于激活了生成器函数,函数才开始执行。执行到yield暂停,等待再次调用next()。
gen.__next__()
# 再次访问生成器
gen.__next__()
# 用next()函数访问生成器
next(gen)
# my_list 求和
print(sum(my_list))
# 迭代器 my_list2 求和
print(sum(my_list2))
# 生成器 gen 求和
print(sum(gen))
附件
本文对应的jupyter notebook源码链接,欢迎下载练习:https://download.csdn.net/download/fx_yzjy101/89785186
如有问题请留言。