包含 yield 关键字的函数,是一个生成器
yield和return的区别
1、return是返回return关键字的值,被调用一次就返回一次,return只能放在一个函数代码块的最后面,运行到return的时候,就结束循环,结束这个函数代码块
2、yield后面可以放置下一行代码,但是每次被循环调用的时候,运行碰到yield就返回yield的值,然后结束这一次调用,内部保留上一次运行的结果,下次调用从yield后面的语句开始执行,直到再次遇到yield
(1)
def testA(a):
b = [1,2,3]
print("调用开始")
for m in range(0,len(b)):
print("---start---")
a.append(m)
yield a
print("x:",a)
def runtestA():
a=[4,5,6]
g = testA(a)
for i in g:
print("y:",i)
runtestA()
#运行结果
调用后
调用开始
---start---
y: [4, 5, 6, 0]
x: [4, 5, 6, 0]
---start---
y: [4, 5, 6, 0, 1]
x: [4, 5, 6, 0, 1]
---start---
y: [4, 5, 6, 0, 1, 2]
x: [4, 5, 6, 0, 1, 2]
解析:程序开始运行,调用testA函数,因为里面包含了yield,所以这个函数没有真正运行,而是得到一个生成器g,当开始for循环 i in g的时候,才开始运行testA函数,这也是为什么打印的“调用后”反而在“调用开始”之前 ;
运行testA函数,进入for循环,打印--start–,程序遇到yield,返回a的值,程序停止,然后在runtestA里面继续执行程序,打印y的值;
接着继续运行,就从刚刚遇到yield之后开始运行,打印x的值,为生成器的第一个值,然后在for循环里面继续运行,打印--start–,遇到yield,程序停止。。。一直重复,直到循环结束
(2)
def testA(a):
b = [1,2,3]
print("调用开始")
for m in range(0,len(b)):
print("---start---")
a.append(m)
yield a
print("x:",a)
def runtestA():
a=[4,5,6]
g = testA(a)
print("调用后")
for i in g:
print("y:",i)
i.pop(0)
print("newy:",i)
#运行结果
调用后
调用开始
---start---
y: [4, 5, 6, 0]
newy: [5, 6, 0]
x: [5, 6, 0]
---start---
y: [5, 6, 0, 1]
newy: [6, 0, 1]
x: [6, 0, 1]
---start---
y: [6, 0, 1, 2]
newy: [0, 1, 2]
x: [0, 1, 2]
解析:程序开始运行,调用testA函数,因为里面包含了yield,所以这个函数没有真正运行,而是得到一个生成器g,当开始for循环 i in g的时候,才开始运行testA函数;
运行testA函数,进入for循环,打印–start–,程序遇到yield,返回a的值,程序停止,到这里都和第一个代码的流程一样;
接着运行 runtestA,打印y的值后,将 第一个i值,也就是[4,5,6,0] 删除了第一位数,打印newy的值:[5,6,0];
接着继续运行,就从刚刚遇到yield之后开始运行,打印x的值,为生成器的第一个值,也就是[5,6,0],接着将第一个值继续投入循环,碰到yield,返回生成器内的第二个值,程序停止,继续运行runtestA,打印y 的值,为[5,6,0,1],接着继续删除列表第一个值,返回newy=[6,0,1],不断循环,直到生成器内循环结束
(3)
def testA(a):
b = [1,2,3]
print("调用开始")
for m in range(0,len(b)):
print("---start---")
a.append(m)
yield a
a = [4,5,6]
print("x:",a)
def runtestA():
a=[4,5,6]
g = testA(a)
print("调用后")
for i in g:
print("y:",i)
i.pop(0)
print("newy:",i)
运行结果: