前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Py3异步编程:yield与yield from

Py3异步编程:yield与yield from

作者头像
歪歪梯
发布2021-10-11 10:06:07
3710
发布2021-10-11 10:06:07
举报
文章被收录于专栏:歪歪梯Club歪歪梯Club

yield

yield把函数变为generator gennerator需要收到一次send(None)或者next才开始执行函数 函数执行了yield语句后,会挂起,直到外部调用send传递一个对象作为yield语句返回值,则继续函数 generator中如果执行return语句也会向常规函数一样终止 yield会执行完下一条语句后,挂起这个方法,保存该语句结果 直到外部调用next或者send才继续方法的执行 比如下面例子

代码语言:javascript
复制
def Test3():
    print("Test3 in")
    for i in range(3):
        s = yield print("do yield test3 %s" % i)
        print("Test3 get %s" % s)
    print("Test3 end")

print("start3")
t = Test3()
print("start3 send")
t.send(None)
print("start3 send end")
for i in range(2):
    print("start3 range %s" % i)
    t.send(i)
print("start3 range end")
"""
--------------------------OUTPUT---------------------
start3
start3 send
Test3 in
do yield test3 0
start3 send end
start3 range 0
Test3 get 0
do yield test3 1
start3 range 1
Test3 get 1
do yield test3 2
start3 range end
"""

未终止的generator(还有yield挂起在等待send)也可以通过调用close方法强行终止

yield from

yield from 迭代器等价于

代码语言:javascript
复制
for xx in 迭代器:
    yield xx

因为next(g)等价于g.send(None)

代码语言:javascript
复制
class Generator(Iterator):
    __slots__ = ()
    def __next__(self):
        return self.send(None)

所以可以这样写

代码语言:javascript
复制
def Test():
    r = yield from [1,2,3,4,5]
    print("t %s" % r)
g = Test()
for i in range(5):
    print(next(g))

嵌套使用

再看看嵌套使用的例子

代码语言:javascript
复制
def InnerYieldPrint(i):
    print("inner yield %s" % i)
    return i

def InnerYield():
    print("InnerYield")
    for i in range(5):#因为是5所以算上启动要外部发送6次
        s = yield InnerYieldPrint(i)
        print("inner get %s" % i)
        print("Test2 give inner %s" % s)
    print("InnerYield end")
    yield 99#因为send每次都要执行到下一个yield语句,才算结束,不然会抛出异常

def Test():
    yield from InnerYield()
    print("yield from end")

def Test2():
    """等价于Test"""
    print("Test2")
    x = InnerYield()
    print("go die")
    iCnt = 0
    for r in x:#等价于 r = next(x),那么第一次就是启动InnerYield
        iCnt += 1
        print("cnt %s" % iCnt)
        print("prepare Test2 %s" % r)
        if iCnt >= 6:
            print("break")
            break
        s = yield r#这里返回作为外面的send返回值了
        print("Test2 %s" % s)
    print("yield from end")
    yield 999#因为send每次都要执行到下一个yield语句,才算结束,不然会抛出异常

g = Test2()
print("start")
print(g.send(None))  # 启动Test2
for i in [-1, -2, -3, -4, -5,]:
    print("pro %s" % i)
    print("pro send res %s" % g.send(i))

 """
--------------------------OUTPUT---------------------
start
Test2
go die
InnerYield
inner yield 0
cnt 1
prepare Test2 0
0
pro -1
Test2 -1
inner get 0
Test2 give inner None
inner yield 1
cnt 2
prepare Test2 1
pro send res 1
pro -2
Test2 -2
inner get 1
Test2 give inner None
inner yield 2
cnt 3
prepare Test2 2
pro send res 2
pro -3
Test2 -3
inner get 2
Test2 give inner None
inner yield 3
cnt 4
prepare Test2 3
pro send res 3
pro -4
Test2 -4
inner get 3
Test2 give inner None
inner yield 4
cnt 5
prepare Test2 4
pro send res 4
pro -5
Test2 -5
inner get 4
Test2 give inner None
InnerYield end
cnt 6
prepare Test2 99
break
yield from end
pro send res 999

 """

这里比较奇特的是,外层函数的yield可以对应里层generator的send,反之不行 所以InnerYield中的yield 99可以改为return 99而Test2中的yield 999不能改为return

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 歪歪梯Club 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • yield
  • yield from
  • 嵌套使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档