【yield】yield 生成器,next()、send()

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

猜你喜欢

转载自blog.csdn.net/weixin_37804469/article/details/129740411