9、【转载】Python生成器generator之next和send运行流程

def consumer():
    r = 'here'
    for i in range(3):
        yield r
        r = '200 OK' + str(i)

c = consumer()
n1 = next(c)
n2 = next(c)
n3 = next(c)

对于普通的生成器,第一个next调用,相当于启动生成器,会从生成器的第一行代码开始执行,直到第一次执行完yield语句后,中断,将r值返回并暂时跳出生成器函数。

然后第二个next调用,进入生成器函数后,从yield语句的下一句语句开始执行,然后重新运行到yield语句,执行后,跳出生成器函数,

后面再次调用next,依次类推。

 

了解了next()如何让包含yield的函数执行后,我们再来看另外一个非常重要的函数send(msg)。

其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做c.next() 和 c.send(None) 作用是一样的

需要提醒的是,第一次调用时,请使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有Python yield语句来接收这个值。

如果在编辑器中将send(None)注释掉,直接发送一个非None的值,则回报错:

Traceback (most recent call last):
  File "D:/PycharmProjects/hello/test.py", line 23, in <module>
    produce(c)
  File "D:/PycharmProjects/hello/test.py", line 18, in produce
    r1 = c.send(n)
TypeError: can't send non-None value to a just-started generator

个人理解:调用send(非None值)传入参数,就要有相对应的yield语句接受参数!第一次调用先调用send(None),与next()作用一样,均是在generator中将程序执行定位到yield语句,为了下次传入非None值时接收。这可能时python的一种机制吧。

 

下面来着重说明下send执行的顺序:

# -*- coding: utf-8 -*-

def consumer():
    r = ''
    while True:
        n1 = yield r
        if not n1:
            return
        print('[CONSUMER] Consuming %s...' % n1)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r1 = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r1)
    c.close()

c = consumer()
produce(c)

当第一次执行c.send(None)时,启动生成器,从生成器函数的第一行代码开始执行,直到第一次执行到 n1 = yield r 后,跳出生成器函数。这个过程中,n1一直没有定义,如图所示:

 

下面运行到 r1 = c.send(1) 时,进入生成器函数,注意这里与调用next的不同。

 这里是从 n1 = yield r 开始执行,把1赋值给n1,但是并不执行yield部分

下面继续从yield的下一语句继续执行,然后重新运行到yield语句,执行 yield r 后,跳出生成器函数!

即send和next相比,只是开始多了一次赋值的动作,其他运行流程是相同的。

 

运行结果:

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK1
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK2
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK3
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK4
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK5

 

备注:转载自http://blog.csdn.net/pfm685757/article/details/49924099,并添加个人的见解

posted on 2018-03-15 20:53 Hello _ world 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/zwb8848happy/p/8576214.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成器Python中的一个对象,它按照某种规律来生成元素的对象。与列表不同,生成器保存了产生元素的算法,并记录了游标的位置,以便下次继续获取数据而不是从头开始。生成器可以通过调用next()方法来逐个获取值,它不会保存所有的数据,每次调用只返回一个值,既能享受列表的好处,又不会占用过多的内存空间。创建生成器可以将一个列表生成式的方括号\[\]改为圆括号(),例如`(i for i in range(0,5))`就创建了一个生成器。\[1\]\[2\] 在使用生成器时,需要注意一些细节。例如,在使用send()方法之前,需要先通过next()方法生成一次数据,否则会出现TypeError: can't send non-None value to a just-started generator的错误。另外,生成器可以使用yield语句来产生值,并可以通过send()方法向生成器发送数据。下面是一个示例代码: ```python def demo(): for i in range(10): res = yield i print('send传入的数据:', res) g = demo() print('next生成的数据:', next(g)) print('send生成的数据:', g.send(6)) ``` 以上代码中,通过调用next(g)获取生成器的下一个值,然后使用g.send(6)向生成器发送数据。\[3\] #### 引用[.reference_title] - *1* [python之三大法器——生成器](https://blog.csdn.net/qq_29049499/article/details/121330302)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [python——生成器详解(2022年9月5日更新了内容)](https://blog.csdn.net/YZL40514131/article/details/119989244)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值