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實際的作用更多而且更加複雜等。

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