# ### 生成器函数
'''
(用def定义,里面含有yield)
# yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
'''
from collections import Iterator,Iterable
# (1) 基本使用
'''如果函数当中包含了yield ,那么这个函数是生成器函数'''
def mygen():
print("one")
yield 1
print("two")
yield 2
print("three")
yield 3
# 初始化生成器函数 => 返回一个生成器对象 ,简称生成器
gen = mygen()
print(isinstance(gen,Iterator))
# 调用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
# res = next(gen)
# print(res)
'''
代码解析:
首先初始化生成器函数 返回生成器对象 简称生成器
同过next进行调用
第一次调用时
print(one)
yield 1 记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回1,等待下一次调用
第二次调用时候
print(two)
yield 2 记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回2,等待下一次调用
第三次调用时候
print(three)
yield 3 记录当前代码执行的位置状态,添加阻塞,暂停在这一行,并返回3,等待下一次调用
第四次调用时
因为没有yield 返回值了 所以直接报错....
'''
# (2) 优化代码
def mygen():
for i in range(1,101):
yield "我的球衣号码是%d" % (i)
# 初始化生成器函数 返回 生成器对象 简称生成器
gen = mygen()
for i in range(50):
res = next(gen)
print(res)
for i in range(30):
res = next(gen)
print(res)
# (3) send 把值发送给上一个yield
'''
### send
# next和send区别:
next 只能取值
send 不但能取值,还能发送值
# send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
'''
def mygen():
print("start")
res = yield 1
print(res)
res = yield 2
print(res)
res = yield 3
print(res)
print("end")
# 初始化生成器函数 返回生成器
'''
send 在第一次调用的时候,必须给参数None gen.send(None)
是一个硬性要求的语法(因为第一次调用的时候,没有遇到上一个yield)
'''
gen = mygen()
res = gen.send(None)
print(res)
res = gen.send(111)
print(res)
res = gen.send(222)
print(res)
# res = gen.send(333)
# print(res)
'''
第一次调用时 ,必须使用gen.send(None)
print(start)
res = yield 1 记录当前代码执行的位置状态 ,添加阻塞并返回1,等待下一次调用
第二次调用时 ,
send 先发送 , 在返回 , 发送给yield 1 res接收到了111这个值
print(111)
res = yield 2 记录当前代码执行的位置状态 ,添加阻塞并返回2,等待下一次调用
第三次调用时 ,
send 先发送 , 在返回 , 发送给yield 2 res接收到了222这个值
print(222)
res = yield 3 记录当前代码执行的位置状态 ,添加阻塞并返回3,等待下一次调用
第四次调用时,
因为没有yield 继续返回了 ,直接报错,越界错误
如果仍然想要执行后面没走完的代码,比如95 96 ,那么要通过try ... except 异常处理来解决
try:
lst = [1,2]
print(lst[99])
except:
pass
'''
### yield from : 将一个可迭代对象变成一个迭代器返回
def mygen():
# yield ["陈桂涛","五金玲","张俊林"]
yield from ["陈桂涛","五金玲","张俊林"]
# 初始化一个生成器函数mygen 返回生成器
gen = mygen()
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
# 用生成器写斐波那契数列
# 1,1,2,3,5,8,13,21.......
def mygen(n):
a = 0
b = 1
i = 0
while i<n:
# print(b)
yield b
a,b = b,a+b
i+=1
gen = mygen(100000)
for i in range(20):
res = next(gen)
print(res)
'''
a = 0
b = 1
a,b = b,a
'''