1.基本使用
函数中,只要有yield,那么返回就是一个yield_obj生成器(==generator==)对象,不会执行函数内部的代码
yield_obj.__next__() == next(yield_obj) 这两个一样的
首次通过yield_obj.__next__()方法会执行yield以上的代码,遇到yield然后返回,
再次执行yield_obj.__next__()方法会执行yield以下的代码,与yield以上的代码,遇到yield然后返回,
再次执行yield_obj.__next__()方法会执行yield以下的代码,与yield以上的代码,遇到yield然后返回,
再次执行......
以此类推
def func():
while True:
print('yield 上面代码')
yield
print('yield 下面代码')
yield_obj = func()#这一步不会执行函数,而是返回generator对象
print('========首次__next__()========')
yield_obj.__next__()
print('========再次__next__()========')
yield_obj.__next__()
print('========再次__next__()========')
yield_obj.__next__()
#执行结果:
'''
========首次__next__()========
yield 上面代码
========再次__next__()========
yield 下面代码
yield 上面代码
========再次__next__()========
yield 下面代码
yield 上面代码
'''
2.generator对象遍历
#generator生成器对象是可以直接通过 for item in iterable 遍历的
def func():
for i in range(5):
yield i
generator_obj = func()#返回一个generator对象
for item in generator_obj:
print('item',item)
#执行结果:
'''
item 0
item 1
item 2
item 3
item 4
'''
3.yield左右两边的数据
yield右边可以接返回值(与return类似),yield左边可以通过“=”接收yield_obj.send()发送的数据
def func():
while True:
print('yield 上面代码')
res = yield 'yield返回值'
print(f'yield 下面代码 send:{res}') # yield 下面代码 send:send发送
yield_obj = func()
print('========yield返回值========')
print(yield_obj.__next__()) # yield返回值
print('========send发送========')
print(yield_obj.send('send发送'))
#执行结果
'''
========yield返回值========
yield 上面代码
yield返回值
========send发送========
yield 下面代码 send:send发送
yield 上面代码
yield返回值
'''
- 注意:yield_obj.send()发送也可以不使用res接收,那么作用跟yield_obj.next()一样了,就是切换到yield下面的代码执行
def func():
while True:
print('yield 上面代码')
yield 'yield返回值'#没有接收send发送,跟yield_obj.__next__()效果一致
print(f'yield 下面代码')
yield_obj = func()
print('========yield返回值========')
print(yield_obj.__next__()) # yield返回值
print('========send发送========')
print(yield_obj.send('send发送'))
#执行结果:
'''
========yield返回值========
yield 上面代码
yield返回值
========send发送========
yield 下面代码
yield 上面代码
yield返回值
'''
4.yield from
基本使用
yield from 后面可以跟的可以是==生成器== 、==元组==、 ==列表==、==range()函数==产生的序列等可迭代对象
作用
简化了代码
def my_generator():
yield from generator1() #yield from iterable本质上等于 for item in iterable: yield item的缩写版
#例如:yield from range(10) 等于 for i in range(10): yield i
yield from range(10)
for i in range(10):
yield i
return的返回值
遍历一个生成器对象,无法获取生成器return的返回值
def my_generator():
for i in range(5):
if i == 2:
return '我被迫中断了'
else:
yield i
def wrap_my_generator(): # 定义一个包装“生成器”的生成器,它的本质还是生成器
result = yield from my_generator() # 自动触发StopIteration异常,并且将return的返回值赋值给yield from表达式的结果,即result
print('result',result)
yield result#再yield出去,就可以遍历获取到
my_g = my_generator()
wrap_g = wrap_my_generator()
print('=======================方式一=======================')
#方式一:遍历无法获取
for j in my_g:
print(j)
# yield无法获取生成器return的返回值
# 遇到return,只是会终止迭代,而不会触发异常,故而也就没办法获取return的值
print('=======================方式二=======================')
#生成器执行一次过后,就没有值了,所以要再创建一个生成器对象
my_g = my_generator()
#方式二:这样才会触发StopIteration,拿到返回值
try:
print(next(my_g)) #每次迭代一个值,则会显式触发StopIteration
print(next(my_g))
print(next(my_g))
print(next(my_g))
print(next(my_g))
except StopIteration as exc:
print('exc.value',exc.value) #获取返回的值
#执行结果:
'''
=======================方式一=======================
0
1
=======================方式二=======================
0
1
exc.value 我被迫中断了
=======================方式三=======================
0
1
result 我被迫中断了
我被迫中断了
'''
数据传输的管道
其实yield from最重要的作用就是提供了一个“数据传输的管道”
def average():
while True:
num = yield 666
print('数据实际上传送到这了',num)
def wrap_average(generator):
yield from generator
wrap_g = wrap_average(average())
next(wrap_g)
wrap_g.send('send')#回到yield下面继续执行
#传送给wrap_average()生成器的,实际上是传送给了average()生成器
#执行结果:
'''
数据实际上传送到这了 send
'''