初识协程
''' 协程中的datum=yield,其中的yild理解为控制流程的方式 ''' def simple_coroutine(): print('-->start coroutine') x = yield print('-->continue coroutine', x) my_coro = simple_coroutine() # print(next(my_coro))#预激协程 # print(my_coro.send(None)) # print(my_coro.send(42)) def simple_coroutine2(a): print('-->start coroutine a=', a) b = yield a print('-->Received b:', b) c = yield a + b print('-->Received c:', c) import inspect my_coro2 = simple_coroutine2(1) #print(inspect.getgeneratorstate(my_coro2)) # GEN_CREATED print(my_coro2.send(None)) #print(inspect.getgeneratorstate(my_coro2)) # GEN_SUSPENDED :在yield处暂停 print(my_coro2.send(2)) try: print(my_coro2.send(3)) except StopIteration as e: print(e.value) #print(inspect.getgeneratorstate(my_coro2)) # GEN_CLOSED :执行结束
# 使用协程创建一个计算平均值的功能 def average(): total = 0.0 count = 0 average = None while True: term = yield average total+=term count+=1 average=total/count avg=average() next(avg) print(avg.send(1)) print(avg.send(2))
# 定义一个协程装饰器,让其预激活到第一个yield处 from functools import wraps def corotine(func): @wraps(func) def primer(*args, **kwargs): gen = func(*args, **kwargs) next(gen) return gen return primer @corotine def average2(): total = 0.0 count = 0 average = None while True: term = yield average total += term count += 1 average = total / count avg = average2() print(avg.send(1))
gen.throw的用法
class DemoException(Exception): '''示例''' def demo_exc(): print('corotione start') while True: try: x = yield except DemoException: print('DemoException handled Continuing...') else: print('corotinue received {!r}'.format(x)) raise RuntimeError('This line should never run!!!') # demo = demo_exc() # next(demo) # import inspect # # print(inspect.getgeneratorstate(demo)) # GEN_SUSPENDED 停在yield # demo.send(1) # # demo.throw(DemoException) # ==== # print(inspect.getgeneratorstate(demo)) # GEN_SUSPENDED 停在yield:说明处理完成了异常继续执行到下一个yield停止 # # try: # demo.throw(StopIteration) # except StopIteration: # pass # print(inspect.getgeneratorstate(demo)) # GEN_CLOSED
取得生成器的值:通过捕获异常的value会得到
yield from的意义
1.子生成器的值都直接传给委派生成器的调用方 2.使用send()方法发给委派生成器的值都直接传给子生成器。 如果发送的值是None,那么会调用子生成器的的__next__()方法。 如果发送的值不是None,那么会调用子生成器的send()方法。 如果调用的方法抛出StropIteratoin异常,那么委派生成器恢复运行。 任何其他异常都会向上冒泡,传给委派生成器。 3.生成器退出是,生成器的return expr表达式会触发StrpIterration(expr)异常抛出。 4.yield from表达式的值是子生成器终止时传给StopIteration异常的第一个参数。