1、yield 生成器
- 生成器函数:函数中有
yield 关键字
的函数,即为 生成器函数(generator function), 比如如下的函数:
def fun_yield():
print("starting yield function")
while True:
result = yield 4
print("result = ",result)
第一次调用 生成器函数,并不会执行函数,只会 返回一个生成器对象
def fun_yield():
print("starting yield function")
while True:
result = yield 4
print("result = ",result)
g = fun_yield() # 第一次调用,并不会执行函数,只会得到一个生成器对象
print(g) # <generator object fun_yield at 0x7f8a17082510>
之后我们可以用 next() 或 send()方法,对 生成器对象进行调用。
2、next()函数 与 send()方法
2.1 next()函数
** 这里我们先将 yield
的作用 简单理解为 return
,我们后面会说 yield 和 return 的区别,看完下面的例子你也自然就懂了(Give it some patience)。
- 获得
生成器对象g
后,第一次对生成器对象g
调用next()
,相当于启动生成器,会从头开始执行 生成器函数,直到 yield语句停止,返回 yield 后面跟的需要返回的值 - 之后,再调用next(), 会从上次执行的节点 yield 语句的下一行开始执行,直到再次遇到 yield 语句。以此循环,直到抛出不可迭代的错误
def fun_yield():
print("starting yield function")
while True:
result = yield 4
print("result = ",result)
g = fun_yield() # 调用这个函数只是会得到一个生成器
print(g)
print("生成器的返回值",next(g))
# starting yield function
# 生成器的返回值 4
print("生成器的返回值",next(g))
# result = None
# 生成器的返回值 4
print("生成器的返回值",next(g))
# result = None
# 生成器的返回值 4
需要注意的是,在执行 result = yield 4
语句的时候,yield 直接把值 4 return 出去了,并没赋值给左边的参数,所以 result
是None。(顺带先提一嘴,如果是 send()
的话,send()会把参数传给 result,比如 send('hello')
, 那么 result='hello'
, 后面细讲 )
yield 与 return
return
作为结尾的普通函数直接返回所有结果,程序终止不再运行,并销毁局部变量;yield
会产生一个断点,暂停函数,挂起函数,保存当前状态。并且在yield处返回某个值,返回之后程序就不再往下运行了。
2.2 send()函数
send()函数
和next()函数
其实很相似,唯一的区别在于send()函数可以传递参数,而next() 函数不能。如下,send() 的参数会赋值给 result- 需要注意的是,创建生成器对象后,第一次调用函数,需要先使用
next()
来启动函数,应为如果第一次就直接使用 send()的话,函数并没有形参 来接受send传递的实参
def fun_yield(): # 第一次调用函数就是用 send()的话,并没有参数 来接受send传递的的参数
print("starting yield function")
while True:
result = yield 4
print("result = ",result)
g = fun_yield()
print(g)
# <generator object fun_yield at 0x7fa3a5082510>
print(next(g)) # 注意这里,第一次调用生成器,需要先使用 next()函数,启动函数
# starting yield function
# 4
print("生成器的返回值",g.send(1))
# result = 1
# 生成器的返回值 4
print("生成器的返回值",g.send(2))
# result = 2
# 生成器的返回值 4
print("生成器的返回值",g.send(3))
# result = 2
# 生成器的返回值 4
生成器在迭代的过程中可以改变当前迭代值,一个特别的例子
def myList(num): # 定义生成器
now = 0 # 当前迭代值,初始为0
while now < num:
val = (yield now) # 返回当前迭代值,并接受可能的send发送值;
now = now + 1 if val is None else val # val为None,迭代值自增1,否则重新设定当前迭代值为val
my_list = myList(5) # 得到一个生成器对象
print(next(my_list)) # 0
print(next(my_list)) # 1
print(my_list.send(3)) # 3
print(next(my_list)) # 4