Python-学习之路-16 协程

2019-03-11  本文已影响0人  末世狂人

协程

迭代器

#isinstance案例

from collections import Iterable
from collections import Iterator

ll = [1,2,3,4,5,6]
#判断是否可迭代
print(isinstance(ll,Iterable))
#判断是否是迭代器
print(isinstance(ll,Iterator))

#转换为迭代器
ll_iter = iter(ll)
#判断是否可迭代
print(isinstance(ll_iter,Iterable))
#判断是否是迭代器
print(isinstance(ll_iter,Iterator))
True
False
True
True

生成器

如果生成一个生成器

# 直接使用生成器
# 放在中括号中是列表生成器
l = [x*x for x in range(5)]
# 放在小括号中就是生成器
g = (x*x for x in range(5))

print(type(l))
print(type(g))
<class 'list'>
<class 'generator'>
# 函数案例
def odd():
    print("step 1")
    yield 1
    print("step 2")
    yield 2
    
g = odd()
one  = next(g)
print(one)
two  = next(g)
print(two)
step 1
1
step 2
2
# for 循环调用生成器
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a ,b = b, a+b
        n +=1
    # 注意,爆出的异常是return返回的值 
    return 'Done'

g = fib(5)

for i in range(6):
    rst = next(g)
    print(rst)
1
1
2
3
5



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-3-e8ff877cca38> in <module>
     12 
     13 for i in range(6):
---> 14     rst = next(g)
     15     print(rst)


StopIteration: Done
ge = fib(10)
'''
生成器的典型用法就是在for循环中使用
'''
for i in ge:
    print(i)
1
1
2
3
5
8
13
21
34
55

参考资料来自:https://blog.csdn.net/andybegin/article/details/77884645

协程的历史

协程的四个状态

#协成的案例1
def simple_coroutine():
    print("-->start")
    x = yield
    print("-->recived",x)
    
# 主线程
sc = simple_coroutine()
print(1111)

# 预激(可以理解为激活协程)
# 同时可以使用se.send(None) 效果与next(sc)一致
next(sc)

print(22222)
#调用协程
sc.send("wangdana")
1111
-->start
22222
-->recived wangdana



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-3-9b0f93417b35> in <module>
     15 print(22222)
     16 #调用协程
---> 17 sc.send("wangdana")


StopIteration: 
# 协成案例2
def simple_coroutine(a):
    print('-> start') 
    b = yield a 
    print('-> recived', a, b) 
    c = yield a + b 
    print('-> recived', a, b, c)
# run 
sc = simple_coroutine(5)
next(sc) 
sc.send(6) # 5, 6 
sc.send(7) # 5, 6, 7

-> start
-> recived 5 6
-> recived 5 6 7



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-3-e9591ee2bc46> in <module>
     10 next(sc)
     11 sc.send(6) # 5, 6
---> 12 sc.send(7) # 5, 6, 7


StopIteration: 

解释:

  1. 调用 next(ag) 函数后,协程会向前执行到 yield 表达式,产出 average 变量的初始值——None。
  2. 此时,协程在 yield 表达式处暂停。
  3. 使用 send() 激活协程,把发送的值赋给 num,并计算出 avg 的值。
  4. 使用 print 打印出 yield 返回的数据。

终止协程和异常处理

显式地把异常发给协程

generator.throw(exc_type[, exc_value[, traceback]])

generator.close()

yield from获取协程的返回值

yield from基本用法

# yield from 案例
def gen():
    for c in 'AB':
        yield c

print(list(gen()))

def gen_new():
    yield from 'AB'

print(list(gen_new()))
['A', 'B']
['A', 'B']

yield from高级用法

yield from 专门的术语

委派生成器:包含 yield from 表达式的生成器函数。
子生成器:从 yield from 中 部分获取的生成器。
from collections import namedtuple 
ResClass = namedtuple('Res', 'count average') 
# 子生成器 
def averager(): 
    total = 0.0 
    count = 0 
    average = None 
    while True: 
        term = yield 
        if term is None: 
            break 
        total += term 
        count += 1 
        average = total / count 
    return ResClass(count, average) 
# 委派生成器 
def grouper(storages, key): 
    while True: 
        # 获取averager()返回的值 
        storages[key] = yield from averager() 
        
# 客户端代码 
def client(): 
    process_data = { 
        'boys_2': [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3], 
        'boys_1': [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46] } 
    storages = {} 
    for k, v in process_data.items(): 
        # 获得协程 
        coroutine = grouper(storages, k) 
        # 预激协程 
        next(coroutine) 
        # 发送数据到协程 
        for dt in v: 
            coroutine.send(dt) 
            # 终止协程 
            coroutine.send(None) 
        print(storages)
# run 
client()

{'boys_2': Res(count=1, average=36.3)}
{'boys_2': Res(count=1, average=36.3), 'boys_1': Res(count=1, average=1.46)}
上一篇下一篇

猜你喜欢

热点阅读