私はjsでそれがawait
ステートメントの前にreturn
を行うために何も追加しないことを知っています(すなわち、return await ...
)ですが、pythonの場合もそうですか。それとも、どういうわけか、具体化の可能性が高くなったり、異なったりしますか?
2つが同等でない場合、ベストプラクティスは何ですか?
与えられた:
async def foo() -> str:
return 'bar'
foo
を呼び出したときに得られるのは Awaitable
で、これは明らかにawait
したい。考える必要があるのは、関数の戻り値です。たとえば、これを行うことができます:
def bar() -> Awaitable[str]:
return foo() # foo as defined above
ここでbar
は同期関数ですが、Awaitable
を返すstr
を返します。
async def bar() -> str:
return await foo()
ここでbar
自体はasync
であり、呼び出されるとAwaitable
になり、上記と同様にstr
になります。これらの2つの使用法には実際の違いはありません。違いはここに表示されます:
async def bar() -> Awaitable[str]:
return foo()
ここでbar
を呼び出すとAwaitable
が生成され、その結果Awaitable
が生成され、str
が生成されます。かなり違う。上記を単純に使用すると、次のような結果が得られます。
>>> asyncio.run(bar())
<coroutine object foo at 0x108706290>
RuntimeWarning: coroutine 'foo' was never awaited
経験則として、async
へのすべての呼び出しは、どこかでawait
edする必要があります。 2つのasync
(async def foo
およびasync def bar
)がawait
にbar
がない場合、bar
の呼び出し元はawait
を2回実行する必要がありますが、これは奇妙です。
TL)@deceze回答のDR。
はい、理由があります。コルーチンを呼び出す場合は、常にreturn await
。
Async
関数は、単純なreturn
であっても、常にAwaitableを返します。実際の結果を取得するには、await
を呼び出します。 return await
がない場合、結果は余分にラップされたAwaitableであり、2回待機する必要があります。ドキュメントを参照してください。
import asyncio
async def nested():
return 42
async def main():
# Nothing happens if we just call "nested()".
# A coroutine object is created but not awaited,
# so it *won't run at all*.
nested()
# Let's do it differently now and await it:
print(await nested()) # will print "42".
asyncio.run(main())