Python迭代器、生成器yield、async/await協(xié)程和異步編程

??本文主要講兩個(gè)方面的東西,一個(gè)是迭代方面,對(duì)應(yīng)是生成器,語(yǔ)法是yield。另一個(gè)方面是異步編程,對(duì)應(yīng)是協(xié)程,語(yǔ)法是async。

yield

??首先生成器是用來(lái)迭代的。所以要先弄清可迭代的,容器,迭代器,生成器的關(guān)系。
??簡(jiǎn)單來(lái)說(shuō),可以for i in x這樣用的x就是可迭代的。它包括容器和迭代器。

容器

??容器就像列表,可以放數(shù)據(jù),為什么可以放for里面迭代呢,方便吧。

迭代器

??迭代器就是實(shí)現(xiàn)__iter__()和__next__()的,__iter__返回自己,__next__返回迭代的下一個(gè)值。在for里其實(shí)是隱式調(diào)用了__next__()。

class Iterator:
    def __init__(self):
        self.data = 0

    def __iter__(self):
        return self

    def __next__(self):
        self.data += 1
        if self.data > 5:
            raise StopIteration
        return self.data


if __name__ == '__main__':
    I = Iterator()
    try:
       for i in  I:
           print(i)
    except StopIteration:
        pass

??迭代器迭代完了后繼續(xù)調(diào)用__next__()結(jié)合觸發(fā)StopIteration錯(cuò)誤。

生成器

??生成器就是一種特殊的迭代器。它外表像函數(shù),但是用yield代替return。調(diào)用生成器會(huì)返回一個(gè)對(duì)象,顯式或隱式(for里面)調(diào)用next就會(huì)執(zhí)行到y(tǒng)ield返回一個(gè)值,然后暫停,下次從這個(gè)地方繼續(xù)。一個(gè)例子如下:

def f(max):
    n = 0
    while n < max:
        yield n
        n += 1


if __name__ == '__main__':
    for i in f(5):
        print(i)

??然后人們就想要是加入send(),可以給生成器發(fā)送信息,不就實(shí)現(xiàn)了協(xié)程么。所以就有了send()函數(shù)。用a = yield *,執(zhí)行到y(tǒng)ield暫停后,下次執(zhí)行,就把send的值賦值給a。

def f(max):
    n = 0
    while n < max:
        a = yield n
        n = n + a + 1


if __name__ == '__main__':
    fun = f(5)
    print(fun.send(None))
    try:
        while True:
            print(fun.send(1))
    except StopIteration:
        pass

??這個(gè)代碼輸出的是0,2,4。當(dāng)然,還有yield from等配合使用。這里就不講了。

async/await

??這個(gè)語(yǔ)法是專門為協(xié)程設(shè)計(jì)的,為了使python更簡(jiǎn)潔好用。async def申明一個(gè)協(xié)程函數(shù),函數(shù)里可以使用await等待其他協(xié)程函數(shù)執(zhí)行完再繼續(xù)執(zhí)行自己的代碼。

async def async_f():
    return 1


async def await_f():
    result = await async_f()
    return result + 1

if __name__ == '__main__':
    try:
        await_f().send(None)
    except StopIteration as e:
        print(e.value)

??輸出2。但是這樣好像沒(méi)什么意義。其實(shí)這兩條語(yǔ)法一般是結(jié)合asyncio標(biāo)準(zhǔn)庫(kù)來(lái)用的。

import asyncio
async def hello():
    print('Send request')
    await asyncio.sleep(1)
    print('Get')


async def cal():
    n = 0
    for i in range(5):
        n += i
    print(n)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    tasks = [hello(), cal()]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()

輸出:
Send request
10(停頓1秒左右)
Get
異步編程適合IO操作,在等待的時(shí)候可以先進(jìn)行其他操作,提高cpu利用率。asyncio正是這么一個(gè)幫忙自動(dòng)切換協(xié)程的庫(kù)。

異步生成器

??這個(gè)名詞不知道準(zhǔn)不準(zhǔn)確,反正就是async和yield結(jié)合用法吧。這是一個(gè)買西紅柿和馬鈴薯的例子。從貨架上一個(gè)一個(gè)拿,沒(méi)有了就叫售貨員加。

import asyncio
all_potatos = [1, 1, 1, 1, 1]
all_tomatos = [1, 1, 1, 1, 1]


async def ask_for_potato():
    all_potatos.append(1)


async def ask_for_tomato():
    all_potatos.append(1)


async def take_potatos(num):
    count = 0
    while True:
        if len(all_potatos) == 0:
            await ask_for_potato()
        potato = all_potatos.pop()
        yield potato
        count += 1
        if count == num:
            break


async def take_tomatos(num):
    count = 0
    while True:
        if len(all_tomatos) == 0:
            await ask_for_tomato()
        tomato = all_tomatos.pop()
        yield tomato
        count += 1
        if count == num:
            break


async def buy_potatos():
    bucket = []
    async for i in take_potatos(50):
        bucket.append(i)
    print(len(bucket))


async def buy_tomatos():
    bucket = []
    async for i in take_potatos(50):
        bucket.append(i)
    print(len(bucket))

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    tasks = [buy_potatos(), buy_tomatos()]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容