1. 生成器的概念
生成器是一类特殊的迭代器,它不需要再像上面的类一样写__iter__()和__next__()方法了, 使用更加方便,它依然可以使用next函数和for循环取值
2. 创建生成器方法1
- 第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
my_list = [i * 2 for i in range(5)]
print(my_list)
# 创建生成器
my_generator = (i * 2 for i in range(5))
print(my_generator)
# next获取生成器下一个值
# value = next(my_generator)
#
# print(value)
for value in my_generator:
print(value)
执行结果:
[0, 2, 4, 6, 8]
<generator object <genexpr> at 0x101367048>
0
2
4
6
8
3. 创建生成器方法2
- 在def函数里面看到有yield关键字那么就是生成器
def fibonacci(num):
a = 0
b = 1
# 记录生成fibonacci数字的下标
current_index = 0
print("--11---")
while current_index < num:
result = a
a, b = b, a + b
current_index += 1
print("--22---")
# 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
yield result
print("--33---")
fib = fibonacci(5)
value = next(fib)
print(value)
value = next(fib)
print(value)
value = next(fib)
print(value)
# for value in fib:
# print(value)
在使用生成器实现的方式中,我们将原本在迭代器__next__方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个生成器了。
简单来说:只要在def中有yield关键字的 就称为 生成器
4.生成器使用return关键字
def fibonacci(num):
a = 0
b = 1
# 记录生成fibonacci数字的下标
current_index = 0
print("--11---")
while current_index < num:
result = a
a, b = b, a + b
current_index += 1
print("--22---")
# 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
yield result
print("--33---")
return "嘻嘻"
fib = fibonacci(5)
value = next(fib)
print(value)
# 提示: 生成器里面使用return关键字语法上没有问题,但是代码执行到return语句会停止迭代,抛出停止迭代异常
# 在python3里面可以使用return关键字,python2不支持
# return 和 yield的区别
# yield: 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
# return: 只能返回一次值,代码执行到return语句就停止迭代
try:
value = next(fib)
print(value)
except StopIteration as e:
# 获取return的返回值
print(e.value)
提示:
- 生成器里面使用return关键字语法上没有问题,但是代码执行到return语句会停止迭代,抛出停止迭代异常
- 在python3里面可以使用return关键字,python2不支持
5. yield和return的对比
- 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
- 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
- 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
- return只能返回一次值,代码执行到return语句就停止迭代,抛出停止迭代异常
6. 使用send方法启动生成器并传参
send方法启动生成器的时候可以传参数
In [10]: def gen():
....: i = 0
....: while i<5:
....: temp = yield i
....: print(temp)
....: i+=1
....:
执行结果:
In [43]: f = gen()
In [44]: next(f)
Out[44]: 0
In [45]: f.send('haha')
haha
Out[45]: 1
In [46]: next(f)
None
Out[46]: 2
In [47]: f.send('haha')
haha
Out[47]: 3
In [48]:
注意:
- 如果第一次启动生成器使用send方法,那么参数只能传入None,一般第一次启动生成器使用next函数
- 生成器创建有两种方式,一般都使用yield关键字方法创建生成器
- yield特点是代码执行到yield会暂停,把结果返回出去,再次启动生成器在暂停的位置继续往下执行