1. 程式人生 > 實用技巧 >對於Python中可被await物件的一點研究

對於Python中可被await物件的一點研究

可被Await的4種物件


Python3.5中新增加了關於async和await語法和定義了何為Coroutines物件,在平時使用時,會分不清哪些能夠await,所以記錄下對於可被await的物件的理解.

根據PEP 492,可被await的物件主要分為4類:

  • Anative coroutineobject returned from anative coroutine function.
  • Agenerator-based coroutineobject returned from a function decorated withtypes.coroutine().
  • An object with an__await__
    method returning an iterator.
  • Objects defined with CPython C API with atp_as_async.am_awaitfunction, returning aniterator(similar to__await__method).

對於以上的4種物件,我將就自己的理解進行下列解釋,如有不同的意見歡迎指點.


1. Async定義的函式

在PEP 492中,同時也定義了async語法,主要用於在函式定義時,使該函式變為一個native coroutine function,也就是在用到async定義的函式時,一樣能被await

async def func():
    pass

async def main():
    await func()

2. 裝飾器types.coroutine()修飾的函式

但是不僅僅使用types.coroutine裝飾器,函式必須使用yield from,並且後面返回一個Coroutine物件(即文中提到的除此之外的其他3種物件)

import types
import asyncio
from tornado.queues import Queue

q = Queue()


@types.coroutine
def run():
    print("This is run")
    yield from q.put(1)


async def main():
    await run()


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

3. 有__await__方法的物件

顧名思義,就是定義了__await__方法的物件也能被await,同時該方法必須返回iterator,否則就會報錯
關於asyncio.future物件可被await,也是添加了__await__ = __iter__這一行
對於該類物件不是很好確定,通常可看原始碼來確定是否具有__await__方法

4. CPython中定義tp_as_async.am_await

還未嘗試過編譯CPython,所以對於這點並不是特別清楚,但是文件中也說了和__await__方法類似,同樣要返回一個iterator


補充延伸:

最初想要搞清楚可被await的物件是因為在學習tornado過程中,要不斷的使用async和await方法,為了在使用時能較清楚的明白使用條件,才去研究了await的使用條件.
而在tornado中,除了以上4點之外,我目前還了解能被await的物件或方法具有一個特徵: 那就是他們都返回Awaitable或Future,比如說tornado.queues中的Queue,在使用過程中,會發現queue中有的方法可以被await,有的方法並不可以,在查看了原始碼之後,發現可被await的方法都是返回一個Future物件,而該物件是來自於asyncio的Future,其中實現了__await__,所以才能被await.


參考文獻:<PEP 492>