栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python3异步编程:yield与yield from

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python3异步编程:yield与yield from

yield

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

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 迭代器等价于

for xx in 迭代器:
	yield xx

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

class Generator(Iterator):
    __slots__ = ()
    def __next__(self):
        return self.send(None)

所以可以这样写

def Test():
    r = yield from [1,2,3,4,5]
    print("t %s" % r)
g = Test()
for i in range(5):
    print(next(g))
嵌套使用

再看看嵌套使用的例子

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

更多文章,请搜索公众号歪歪梯Club

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/283800.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号