Python中await用户自定义类实例的执行机制是什么?
Python中
await关键字的深入解析 Python官方文档指出:
await是Python的关键字,通常有两种使用方式:await task await coroutine
await的行为很大程度上取决于被等待对象的类型。
在相关章节中提到:
- “coroutine(协程)”与“coroutine object(协程对象)”是同义词。
- “coroutine object(协程对象)”由调用“coroutine function(协程函数)”(也称为“asynchronous function(异步函数)”,二者为同义词)创建。
示例如下:
async def loudmouth_penguin(magic_number: int): print( "I am a super special talking penguin. Far cooler than that printer. " f"By the way, my lucky number is: {magic_number}." ) obj = loudmouth_penguin(magic_number=3)
在此示例中,loudmouth_penguin是“协程函数”(或“异步函数”),obj是“协程对象”(或“协程”)。
Task(任务)可通过asyncio.create_task函数创建:
task = asyncio.create_task(coroutine)
回到await的行为:
- await一个task会将当前task或协程的控制权交还给事件循环
- 与task不同,await一个协程不会将控制权交还给事件循环!
await coroutine的行为实际上与调用普通同步Python函数相同。
接下来是一个示例(添加了更多打印语句来观察执行过程):
class Rock: def __await__(self): print(f"\t\tRock.__await__ called") value_sent_in = yield 7 print(f"\t\tRock.__await__ resuming with value: {value_sent_in}.") return value_sent_in async def main(): print(f"\tBeginning coroutine main().") rock = Rock() print(f"\tAwaiting rock...") value_from_rock = await rock print(f"\tCoroutine received value: {value_from_rock} from rock.") return 23 print(f"Calling coroutine") coroutine = main() intermediate_result = coroutine.send(None) print(f"Coroutine paused and returned intermediate value: {intermediate_result}.\n") print(f"Resuming coroutine and sending in value: 42.") try: coroutine.send(42) except StopIteration as e: returned_value = e.value print(f"Coroutine main() finished and provided value: {returned_value}.")
运行结果如下:
Calling coroutine Beginning coroutine main(). Awaiting rock... Rock.__await__ called Coroutine paused and returned intermediate value: 7. Resuming coroutine and sending in value: 42. Rock.__await__ resuming with value: 42. Coroutine received value: 42 from rock. Coroutine main() finished and provided value: 23.
在此示例中,我们使用await的方式是官方文档未提及的:等待一个用户自定义类的实例(即value_from_rock = await rock这行代码)。
当我们await用户自定义类的实例时,会发生什么?官方文档未说明,只能自行推测。
推测其行为是:立即调用该类的__await__成员函数(不会将控制权交还给事件循环)并返回结果?
也就是说:
value_from_rock = await rock
实际上等同于:
value_from_rock = rock.__await__() yield value_from_rock
?
注意:在执行value_from_rock = await rock之后,下一行代码:
print(f"\tCoroutine received value: {value_from_rock} from rock.")
在首次调用协程时并未执行,看起来像是立即返回了。
内容的提问来源于stack exchange,提问作者robertspierre
相关产品推荐
相关产品推荐

