python协程的相关总结

生成器

可迭代对象、迭代器、生成器

  • 可迭代对象:实现了方法__iter__或__getitem__就是可迭代的。
  • 迭代器:在可迭代对象的基础上实现了__next__方法,__iter__方法需返回一个迭代器,如果自身是迭代器则返回self。
  • 生成器:可以理解为在迭代器的基础上再实现了yield,yield返回新的值后,会在当前位置阻塞,等待下一次的调用。

如何激活生成器

  • next()
  • generator.send(None)

生成器的执行状态

  • GEN_CREATED
  • GEN_RUNNING
  • GEN_SUSPENDED
  • GEN_CLOSED

生成器的异常处理

当生成器不满足生成元素的条件时,就应该抛出异常StopIteration

从生成器过度到协程

协程是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序。

如何向生成器中发送消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def jumping_range(N):
index = 0
while index < N:
# 通过send()发送的消息将赋值给jump
jump = yield index
if jump is None:
jump += 1
index += jump


if __name__ == '__main__':
itr = jumping_range(5)
print(next(itr)) # 0
print(itr.send(2)) # 2
print(next(itr)) # 3
print(itr.send(-1)) # 2

重点在于jump = yield index

  • yield index 是将index return给外部调用程序
  • jump = yield 是可以接收外部程序通过send()发送的信息,并赋值给jump

yield from 语法

为什么要使用协程

如果没有协程,要去实现一个并发程序,可能会有以下问题

  1. 使用最常规的同步编程要实现异步并发效果并不理想,或者难度极高
  2. 由于GIL锁的存在,多线程的运行需要频繁的加锁解锁,切换线程,这极大的降低了并发性能

而协程的出现,刚好可以解决以上的问题,它的特点有

  1. 协程是在单线程里实现任务的切换的
  2. 利用同步的方式去实现异步
  3. 不再需要锁,提高了并发性能

yield from用法详解

yield from 是在python3.3才出现的语法。这个特性是在python2中没有的。
yield from 后面是需要加可迭代对象,它可以普通的可迭代对象,也可以是迭代器,甚至是生成器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# usage: yield
def gen_1(*args, **kwargs):
for item in args:
for i in item:
yield i

def gen_2(*args, **kwargs):
for item in args:
yield from item

str_1 = "test"
list_1 = [1, 2, 3]

ret_1 = gen_1(str_1, list_1)
ret_2 = gen_2(str_1, list_1)

# ['t', 'e', 's', 't', 1, 2, 3]

生成器嵌套

  1. 调用方:调用委托生成器的客户端代码
  2. 委托生成器:包含yield from的表达式生成器函数
  3. 子生成器:yield from 后面加的生成器函数