Python协程的理解

Python协程的理解

1. Python中yield的理解

def call(k):
    return k*3
def yield_test1(n):
    for i in range(n):
        z = yield call(i)
        print("z:j=%s" % i)

n = yield_test1(10)
print(next(n))
print(n.send(11))

执行结果

0
z:j=0
3

Process finished with exit code 0
  • 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator(生成器)。
  • next(n)相当于send(None),每一执行next或send时,程序遇到yield的时候暂停,并将yield 同行的语句返回(有点类似return)。
  • 第一次执行next(n)执行到yield call(i),返回结果0。第二次send(11)将执行,print(“z:j=%s” % i), yield call(i),返回结果打印z:j=0,返回值3。
  • yield执行到最后抛出StopIteration错误表示无法继续返回下一个值了,本例中for语句自带捕获StopIteration异常,终止循环,其他的情况可能会需要进行异常处理。
  • generator(生成器)一般没有return语句,如果任然要写return “123”语句,但是无法正常获得这个值,需要按照以下方法:
def fib(max):
  n, a, b = 0, 0, 1
  while n < max:
    yield b
    a, b = b, a + b
    n = n + 1
  return 'done'
# 捕获Generator的返回值
g = fib(6)
while True:
  try:
    x=next(g)
    print('g=',x)
  except StopIteration as e:
    print('Generrator return value:', e.value)
    break

执行获取结果:

g= 1
g= 1
g= 2
g= 3
g= 5
g= 8
Generrator return value: done

2. Python中yield from的理解

#输出斐波那契數列前 N 个数
def fab3(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1

def f_wrapper1(f):
    for g  in f:
        yield g
wrap = f_wrapper1(fab3(5))
for i in wrap:
    print(i,end=' ')

输出结果:

1 1 2 3 5 
Process finished with exit code 0

使用yield from修改(使用yield from代替for循环)

#输出斐波那契數列前 N 个数
def fab3(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1

def f_wrapper2(f):
  yield from f  # 注意此处必须是一个可生成对象
wrap = f_wrapper2(fab3(5))
for i in wrap:
  print(i, end=' ')

yield from iterable本质上等于for item in iterable: yield item的缩写版

print('yield from包含多个子程序')
def g(x):
    yield from range(x, 0, -1)
    yield from range(x)
print(list(g(5)))
for g  in g(6):
    print(g,end=',')

利用yield from语句向生成器(协程)传送数据

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。
如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,换回生产者继续生产,效率极高:
import time
def consumer_work(len):
  # 读取send传进的数据,并模拟进行处理数据
  print("writer:")
  w = ''
  while True:
    w = yield w  # w接收send传进的数据,同时也是返回的数据
    print('[CONSUMER] Consuming %s...>> ', w)
    w *= len  # 将返回的数据乘以100
    time.sleep(0.1)


def consumer(coro):
  yield from coro  # 将数据传递到协程(生成器)对象中


def produce(c):
  c.send(None)  # "prime" the coroutine
  for i in range(5):
    print('[Produce] Producing %s----', i)
    w = c.send(i)  # 发送完成后进入协程中执行
    print('[Produce] receive %s----', w)
  c.close()


c1 = consumer_work(100)
produce(consumer(c1))

执行结果:

writer:
[Produce] Producing %s---- 0
[CONSUMER] Consuming %s...>>  0
[Produce] receive %s---- 0
[Produce] Producing %s---- 1
[CONSUMER] Consuming %s...>>  1
[Produce] receive %s---- 100
[Produce] Producing %s---- 2
[CONSUMER] Consuming %s...>>  2
[Produce] receive %s---- 200
[Produce] Producing %s---- 3
[CONSUMER] Consuming %s...>>  3
[Produce] receive %s---- 300
[Produce] Producing %s---- 4
[CONSUMER] Consuming %s...>>  4
[Produce] receive %s---- 400

Process finished with exit code 0

3. Python中@asyncio.coroutine的理解

4. Python中asyncio和aiohttp的理解

猜你喜欢

转载自blog.csdn.net/adobeid/article/details/81002776