Python yield
1、定义
函数中带有关键字yield,就是 generator(生成器),带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator(生成器)
2、解释
这个生成器(就说是函数吧)每次执行到 yield 关键 时,函数就返回yied后面的值,yied后面的代码将不再执行(相当于直接return)。下次在调用生成器的next()函数,代码从 yield 关键词 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
3、实战中寻找真理 next()函数
def fabNum():
print("starting...")
while True:
num = yield 2
print("num的值为:",res)
g = fabNum()
print(next(g))
print("-"*20)
print(next(g))
执行结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\python.exe F:/python-space/test/ProTest.py
starting...
2
--------------------
num的值为: None
2
下面需要我们要有一点儿耐心,我们来一步一步的分析:
1)程序开始执行以后,因为fabNum函数中有yield关键字,所以fabNum函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)
2)直到调用next方法,fabNum函数正式开始执行,先执行fabNum函数中的print方法,然后进入while循环
3)程序遇到yield关键字,然后把yield想成return,return了一个2之后,程序停止,并没有执行赋值给num操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果,
4)程序执行print("-"*20),输出20个*
5)又开始执行下面的print(next(g)),这个时候和上面那个差不多,不过不同的是,这个时候是从刚才那个next程序停止的地方开始执行的,也就是要执行num的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候num赋值是None,所以接着下面的输出就是num:None,
6)程序会继续在while里执行,又一次碰到yield,这个时候同样return 出2,然后程序停止,print函数输出的2就是这次return出的2.
4、实践中寻找真理 send()函数
def fab():
print("starting...")
while True:
num = yield 2
print("num的值为:",num)
g = fab()
print(next(g))
print("-"*20)
print(g.send(3))
输出结果:
starting...
2
--------------------
num的值为: 3
2
从上面的2次打印结果对比,可以看出那个num的值从None变成了3,这到底发生了什么呢?
因为生成器的send()函数可以发送一个参数给num,调用next()函数,return的时候,并没有把2赋值给num,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 2之后)执行,先把3赋值给了num,然后执行next的作用,遇见下一回的yield,return出结果后结束。
1)程序执行g.send(3),程序会从yield关键字那一行继续向下运行,send会把3这个值赋值给num变量
2)由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环
3)程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。
5、生成器优点
1)使用方便
2)比rang()函数(生成的结果是list,list是需要优化的)生成的占用更少的存储空间
def foo(num):
print("starting...")
while num<10:
num=num+1
yield num
for n in foo(0):
print('生成的数字是:',n)
结果:
生成的数字是: 1
生成的数字是: 2
生成的数字是: 3
生成的数字是: 4
生成的数字是: 5
生成的数字是: 6
生成的数字是: 7
生成的数字是: 8
生成的数字是: 9
生成的数字是: 10
6、给大佬奉茶
源码:
#1、生成器的简单使用
print('1、生成器的简单使用')
def fabNum():
print("starting...")
while True:
num = yield 4
print("num的值为:",num)
g = fabNum()
print(next(g))
print("-"*20)
print(next(g))
#2、生成器send()的使用
print()
print('*'*20)
print('2、生成器send()的使用')
def fab():
print("starting...")
while True:
num = yield 2
print("num的值为:",num)
g = fab()
print(next(g))
print("-"*20)
print(g.send(3))
#3、举个例子
print()
print('3、举个例子')
def foo(num):
print("starting...")
while num<10:
num=num+1
yield num
for n in foo(0):
print('生成的数字是:',n)
结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\python.exe F:/python-space/test/ProTest.py
1、生成器的简单使用
starting...
4
--------------------
num的值为: None
4
********************
2、生成器send()的使用
starting...
2
--------------------
num的值为: 3
2
3、举个例子
starting...
生成的数字是: 1
生成的数字是: 2
生成的数字是: 3
生成的数字是: 4
生成的数字是: 5
生成的数字是: 6
生成的数字是: 7
生成的数字是: 8
生成的数字是: 9
生成的数字是: 10
Process finished with exit code 0