python asyncio前篇

对于了解asyncio之前我们先需要了解什么是协程,了解协程之前我们需要先了解yield关键字

yield是一个在python中独有的关键字,可以和if for等流程控制语句归为一类,但是却有所不同,应该是说比他们丰富太多
英文意思表示的是让步和产出其实这两个词就可以概括yield的本质了。

官方的定义:一个函数加了yield那么就成为了生成器。更确切的定义是表示语句运行到yield处会暂停,可以输出值,或者交出运行权给其他的语句。

yield前置知识:迭代器
在讨论迭代器之前我们需要知道什么是可迭代和迭代协议

可迭代就表示的是一个对像可以被for来循环
比如:
for i in “asdasd”:
print(i)

a
s
d
a
s
d

那为什么一个对象可以迭代呢,其实对象内部只要实现__iter__函数就行了,注意__iter__必须要返回一个对象有__next__方法否则会报错

class A:
def iter(self):
print(123)
return B()

class B:
def next(self):
print(456)
return “dad”

a = A()
b = iter(a)
print(b)
print(next(b))

运行结果
#123
<main.B object at 0x000000000284EE80>
456
#dad

而如果我们按下面的方式写,是使用for循环
class A:
def iter(self):
print(123)
return self

def next(self):
print(456)
return “dad”

a = A()
for i in a:
print(i)

运行结果
#123
#456
#dad

由此我们得出的结论:
1,一个对象能被iter()那么就是可以迭代的
2,一个对象如果同时可以被iter()和next()那么就是迭代器

最早的时候yield是被当做迭代器使用的
因为生成器的基本使用方式就和迭代器很像:
def a():
yield 1
yield 2
yield 3

a = a() #获取生成器对象,效果相当于是__iter__在执行
print(next(a))
print(next(a))
print(next(a))

运行结果:
#1
#2
#3

由此生成器不就正是做迭代器的好方式么,不用写__iter__和__next__两个方法直接就可以实现迭代器

yield from 的使用:
yield from主要有两大作用,总的来说就是来简化yield的使用:
1,代替产出值的嵌套for循环
2,打开双向通道,让调用方和子生成器连接起来,这样二者可以直接发送和产出值,还可以传入异常,而不用在位于中间的协程添加大量的异常处理的样板代码

对应用法一例子:
def a():
b = [1,2,3,4,5]
for i in b:
yield b

而我们使用yield from 可以这么写:
def a():
b = [1,2,3,4,5]
yield from b

2,对应第二种我们可以这么理解
在这里插入图片描述
#def simple_coroutine():
print(’-> coroutine start’)
x = yield from kk()
print(x)

#子生成器
def kk():
yield 123
return 456

a = simple_coroutine()
调用方
for i in a:
print(i)

运行结果:
-> coroutine start
123
456

总结:
return 返回的是 yiled from的结果,并赋值给后面的x
yield 返回的值是直接传输给调用方
这样的使用方式 就可以很简单的做到生成器嵌套和exception传递

协程:本质上也就是来利用 yield的原理,生成器只能产出值,而协程是可以传入值。一般会写成式子形式(a = yield 6+3)
二者都是需要进行预激。由此产生了一个问题,很多时候由于都在使用yield(因为有的协程也不用传值)造成混乱,搞不清楚是协程还是生成器。python 统一给协程定义了新的关键字,那就是async/await

此时我们对协程已经有了初步的了解,那么和asyncio有关系呢,原因很简单,我们前面都只是在讨论yield的运行中产出值的特性,那么它还有一个特性就是:让步。正式因为让步的特性,每次运行到yield语句其实CPU的运行权限已经交给别的执行语句了,此时这里在进行IO等待(IO多路复用)。所以,当只有一个协程的时候是无法发挥yield的让步特性,那么就需要使用多个协程。现在我们都知道,使用一个协程都需要预激,然后需要使用next,多个协程一起运行我们手动是管理不过来的,于是就需要我们将协程交给它运行,由此asyncIO就是做这件事情的,通过一个IOloop的运行,我们将协程绑定到这个IOloop上面,async对这个IOloop进行管理,从而达到多个协程同时运行的效果。

以上就是yield到asyncio的由来,其中很多地方都有省略,比如yield有四种运行状态,以及yield from的工作细节,asyncio实际的作用更多而且更加复杂等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章