我刚刚发现了一些令人惊讶的事情。考虑以下示例:
import asyncio
async def wait_n(n):
asyncio.sleep(n)
async def main(fn):
print("meh")
await fn(1)
print("foo")
loop = asyncio.get_event_loop()
loop.run_until_complete(main(wait_n))
运行此命令时,我们正确地收到以下警告:
awaitable_lambda.py:5: RuntimeWarning: coroutine 'sleep' was never awaited
asyncio.sleep(n)
这是因为在wait_n
中我们呼叫asyncio.sleep(n)
而没有await
。
但现在考虑第二个示例:
import asyncio
async def main(fn):
print("meh")
await fn(1)
print("foo")
loop = asyncio.get_event_loop()
loop.run_until_complete(main(lambda n: asyncio.sleep(n)))
这次我们使用的是lambda
,令人惊讶的是,即使没有await
,代码也能正常工作。
我了解我们不能在Python await
表达式中使用lambda
,因此这似乎是一项改善人体工程学的功能,但它给我带来了一些问题:>
await
?答案 0 :(得分:10)
任何异步函数都返回awaitable。您不需要立即进行“ await
函数调用”,而最终只需要await
返回所返回的等待值。也就是说,这两个是等效的:
await asyncio.sleep(1)
awaitable = asyncio.sleep(1)
await awaitable
这样,应该很容易看到lambda的调用fn(1)
(隐式地)返回了一个awaitable,而await
等待着它。另一方面,async def wait_n
永远不会返回等待的sleep
,也永远不会等待它本身。
作为一个推论性示例,如果您在async
函数周围有任何包装,则不一定需要该包装本身就是async
:
def add_1(func):
def wrapper(a):
return func(a + 1) # passes the awaitable return value through
return wrapper
@add_1
async def foo(a):
await asyncio.sleep(a)
async def main():
await foo(1)