生成器 & yield

参考: 如何更好地理解Python迭代器和生成器? - 赖明星的回答 - 知乎
https://www.zhihu.com/question/20829330/answer/133606850

send(msg)next()的区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10

生成器 & yield_第1张图片
示例

主要用法

一、定义生成器,上下文切换

def gen():
    # do something (a)
    yield item # (b)
    # do something (c)

for i in gen():
    # do something with i (d)

通过 yield 定义生成器,生成器中可以有多个 yield 的地方,每次 yield 调用,都会有一次上下文切换,会将当前线程的控制权转交到外部代码中。

在生成器调用的时候,首先调用生成器函数 gen,其返回生成器,这个时候先运行 (a) 部分代码,用于生成器环境的初始化,(b) 第一次调用 yield,将 item 返回,上下文开始切换。

外部代码的 for 循环,会将生成器返回的 item 赋值给变量 i,然后运行示例代码中的 (d) 位置,之后进入下一次循环,这个时候上下文再次切换,切换到了生成器函数内部,开始运行 (c) 部分。

这样程序就结束了,因为这里代码只是简单没有循环,只会 yield 一次数据。对于生成器 yield 多次,其运行顺序的分析方式是一样的,主要理解上下文切换

二、增强功能

yield 本身带有的上下文切换能力,缺乏生成器和外部的通信功能,数据是单向的,只能生成器往外部 yield 数据,外部无法传数据给生成器。

def consumer():
    while True:
        i = yield
        print i


def producer(c):
    while True:
        c.send('product')
        yield


if __name__ == '__main__':
    c = consumer()
    c.send(None)
    p = producer(c)
    p.next()
    p.next()
    p.next()
    p.next()

生成器表达式(Generator Expression)

items = (x for x in range(5))

你可能感兴趣的:(生成器 & yield)