Asynchronous IO-coroutine yield from

Let's first look at the difference between yield and yield form. The code is as follows, all passed into range (10)

def g1(iterable):
    yield iterable

def g2(iterable):
    yield from iterable

for value in g1(range(10)):
    print(value)

for value in g2(range(10)):
    print(value)

Result: yield outputs range (10), and yield from outputs his iteration data.

range(0, 10)
0
1
2
3
4
5
6
7
8
9

Before learning yield from, first recognize a library: chain, this library can iterate any number of data, including list, dict, etc.

from itertools import chain 

my_list = [1,2,3]

my_dict = {
    "bobby":"http://project.com",
    "bobby2":"http://www.immoc.com"

}
for value in chain(my_dict,my_list,range(5,10)):
    print(value)

The function it implements is like this, iterating over the data in it one by one

bobby
bobby2
1
2
3
5
6
7
8
9

Now we implement a chain ourselves

# 自定义一个chain
def my_chain(*args,**kwargs):
    for my_iterable in args:
        for value in my_iterable:
            yield value

for value in my_chain(my_dict,my_list,range(5,10)):
    print(value)

The resulting value is also

bobby
bobby2
1
2
3
5
6
7
8
9

Now, realize it with yield from

def my_chain(*args,**kwargs):
    for my_iterable in args:
        yield from my_iterable  # yield from可以迭代其中的所有数据
for value in my_chain(my_dict,my_list,range(5,10)):
    print(value)

 The generated results are as follows.Yield from simplifies the above code.In fact, yield from not only iterates all the data, but also implements a lot of exception handling internally.

bobby
bobby2
1
2
3
5
6
7
8
9

 And using the usage method of yield from, he will establish a two-way channel between the caller and the sub-generator, they realize the connection

def g1(gen):
    yield from gen

def main():
    g = g1()
    g.send(None)

# main 调用方 g1(委托生成器),gen子生成器
# yield from 会在调用方和子生成器之间建立一个双向通道

This is an example of yield from actual combat, 


final_result = {}


def sales_sum(pro_name):
    total = 0
    nums = []
    while True:
        x = yield
        print(pro_name+"销量:",x)
        if not x:
            break
        total+=x
        nums.append(x)
    return total,nums



def middle(key):
    while 1:
        final_result[key] = yield from sales_sum(key)
        print(key+"销量统计完成!")



def main():
    data_set = {
        "bobby牌面膜":[1200,1500,3000],
        "bobby牌手机":[1600,1700,13000,1200],
        "bobby牌大衣":[2300,2100,10,60]
    }
    for key,data_set in data_set.items():
        print("start key",key)
        m = middle(key)
        m.send(None) # 预激活middle协程
        for value in data_set:
            m.send(value) # 给协程传递每一组的值
        m.send(None)
    print("final_result",final_result)

"""
# 详细剖析
"""
def sales_sum1(pro_name):
    total = 0
    nums = []
    while True:
        x = yield
        print(pro_name+"销量:",x)
        if not x:
            break
        total+=x
        nums.append(x)
    return total,nums



if __name__ == '__main__':
    my_gen  =sales_sum1("boobby牌手机")
    my_gen.send(None)
    my_gen.send(1000)
    my_gen.send(1300)
    my_gen.send(1200)
    try:
        my_gen.send(None)# 会异常,把返回值显示出来
    except StopIteration as e:# 需要处理异常
        result = e.value
        print(result)  # yield from会实现这些功能处理异常并返回值

 The final effect is like this, you can copy the above code, analyze and run it in the IED. This involves the use of yield from above. It involves the caller, the delegate generator and the sub-generator, and The sub-generator will implement a bidirectional channel with the caller.

boobby牌手机销量: 1000
boobby牌手机销量: 1300
boobby牌手机销量: 1200
boobby牌手机销量: None
(3500, [1000, 1300, 1200])

 

Published 89 original articles · won praise 2 · Views 2803

Guess you like

Origin blog.csdn.net/qq_37463791/article/details/105481936