1.基于生成式構(gòu)造帶狀態(tài)的函數(shù)
一個(gè)函數(shù)多次調(diào)用都從上次返回的地方重新開(kāi)始葱跋,相當(dāng)于給一個(gè)機(jī)會(huì)從函數(shù)執(zhí)行的中間切出去,再切回來(lái)的時(shí)候從原來(lái)的地方重新開(kāi)始殴蹄,這樣能避免那種需要在函數(shù)執(zhí)行過(guò)程中保留過(guò)多上下文信息的問(wèn)題熄阻。對(duì)于異步io跪另,如果我們能保留函數(shù)上下文,在等待異步io返回的時(shí)候切出去佳遣,這樣就不需要費(fèi)力寫(xiě)回調(diào)鏈了识埋,一切就像同步調(diào)用一樣,await一下零渐,返回之后繼續(xù)窒舟。唯一的問(wèn)題在于,異步io本身是有傳染性的诵盼,為了最大程度利用io等待的時(shí)間惠豺,我們實(shí)際希望協(xié)程在異步io切出去之后,程序能繼續(xù)調(diào)度其它task
2.sleep函數(shù)實(shí)現(xiàn)
@types.coroutine
def __sleep0():
"""Skip one event loop run cycle.
This is a private helper for 'asyncio.sleep()', used
when the 'delay' is set to 0. It uses a bare 'yield'
expression (which Task.__step knows how to handle)
instead of creating a Future object.
"""
yield
async def sleep(delay, result=None, *, loop=None):
"""Coroutine that completes after a given time (in seconds)."""
if delay <= 0:
await __sleep0()
return result
if loop is None:
loop = events.get_event_loop()
future = loop.create_future()
h = loop.call_later(delay,
futures._set_result_unless_cancelled,
future, result)
try:
return await future
finally:
h.cancel()
這個(gè)地方是個(gè)很好的例子风宁,用Future類封裝事件等待洁墙,避免關(guān)心套接字相關(guān)的細(xì)節(jié),但也意味著戒财,我們?nèi)绻M麑⒃械膇o操作變成異步型的話热监,要么封裝自己的協(xié)程,像sleep這樣饮寞,將程序變成loop.run_until_complete孝扛,要么就是程序庫(kù)自己提供了兼容asyncio的接口。