2018.10.17Class_30_Python-27协程

迭代器

  • 可迭代(Iterable):直接作用于for循环的变量
    迭代器(Iterator):不但可作用于for循环,还可以被next调用
    list是典型的可迭代对象,但不是迭代器
    通过isinstance判断
    iterable和iterator可以转换
    通过iter函数
#可迭代
l = [ i for i in range(10)]

#list是可以迭代的,但不是迭代器
for idx in l:
    print(idx)
# range是个迭代器
for i in range(5):
    print(i)
#list
from collections import Iterable
l1 = [1,2,3,4,5]

print(isinstance(l1,Iterable))

from collections import Iterator
print(isinstance(l1,Iterator))

生成器
generator:一边循环一遍计算下一个元素的算法
需要满足三个条件
每次调用都生产出for 循环需要的下一个元素
如果达到最后一个,爆出stopIteration异常
可以被next函数调用
如何生成一个生成器
直接使用
如果函数中包含yield,则这个函数就叫做生成器
next 调用函数,遇到yield返回

#直接使用生成器

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


print(type(L))
print(type(g))
#函数案例
def odd():
    print("Step 1")
    print("Step 2")
    print("Step 3")
    return None
odd()
#生成器的案例

def odd():
    print("Step 1")
    yield 1
    print("Step 2")
    yield 2
    print("Step 3")
    yield 3
g= odd()   

odd()
one = next(g)
print(one)

two = next(g)
print(two)

three = next(g)
print(three)
#for 循环生成器
def fib(max):
    n,a,b = 0,0,1
    while n <max:
        yield b
        a,b= b,a+b
        n=n+1
    return 'done'
g=fib(5)


for i in range(6):
    rst =next(g)
    print(rst)
    
ge = fib(10)
'''生成器的典型用法是在for中使用
比较常见的典型生成器是range
'''

for i in ge:
    print(i)

协程序

  • 历史进程
    -3.4引入协程,用yield实现
    - 3.5引入协程语法
    - 实现的协程比较好的包有asyncio,tornado,gevent
  • 定义:协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口的点在不同位置暂停或者开始执行程序.
  • 从技术角度讲,协程就是一个你可以暂停执行的函数,或者干脆把协程理解成生成器.
  • 协程的实现:
    • yield返回
    • send调用
#协程代码案例1

def simple_coroutine():
    print('->start')
    x= yield
    print('->recived',x)
    
sc=simple_coroutine()
print(1111)
#可以使用sc.send(none),效果一样
next(sc)
print(22222)
sc.send('dfd')
  • 协程的四个状态
    - inspect.getgenratorstate()函数确定,该函数会返回下述字符中的一个:
    - GEN_CREATED:等待开始执行
    - GEN_SUSPENED:在yield表达式处暂停
    - GEN_CLOSED:执行结束
    - nex预激活(prime)
    -代码案例V2
#案例V2,协程状态
def simple_coroutine(a):
    print("start")
    
    b=yield a
    print("recived",a,b)
    
    c = yield a+b
    print("recived",a,b,c)
#runc
sc =simple_coroutine(5)
aa=next(sc)
print(aa)
bb=sc.send(6)
print(bb)
cc=sc.send(7)
print(cc)

协程终止

  • 协程中未处理的异常会往上冒泡,传给next函数或者send方法的调用方(即触发协程的对象)

  • 停止协程对的一种方法:发送某个哨符值,让协程退出.内置的NONE和ELLIPSIS等敞亮经常用作哨符值==.

  • yield from

    • 调用协程为了得到返回值,协程必须正常终止
    • 生成器正常终止会发出stopIteration异常,异常对象的vlaue属性保存返回值
    • yield from从内部捕获 StopIteration异常
    • 案例V3
    def gen():
            for c in "AB":
                yield c
        #list 直接生成器作为参数
        print(list(gen()))
        def gen_new():
            yield from "AB"
        print(list(gen_new()))
  • 委派生成器
    • 包含yield from表达式的生成器函数
    • 委派生成器在yield from表达式暂停,调用方法可以直接把数据发给子生成器
    • 子生成器把产生出的值发给调用方
    • 子生成器在最后,解释器会抛出StopIteration异常
  • 案例V4

案例v4

#案例V4
from collections import namedtuple

Result=namedtuple('Result','average number')

def subaverager():#子生成器
    total = 0.0
    number = 0
    average = None
    while True:
        term = yield
        if term is None:
            break
        total += term
        number += 1
        average=total/number
    return Result(average,number)

def averager(results,key):#委派生成器
    while True:
        results[key]=yield from subaverager()

def main(grouper):
    results={}
    for key,group in grouper.items():
        term = averager(results,key)
        next(term)
        for value in group:
            term.send(value)
        term.send(None)
        print(results)#调试使用
    result(results)
    
def result(results):
    for key,value in results.items():
        gender,unit=key.split(';')
        print('{} {} averaging {:.2f} {}.'.format(
            value.number,gender,value.average,unit))

data = {
'girls;kg':
[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
'girls;m':
[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
'boys;kg':
[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys;m':
[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}

if __name__=='__main__':
    main(data)

猜你喜欢

转载自blog.csdn.net/weixin_42879237/article/details/83118163