上記のソリューションは、コルーチン関数を渡すと単純なケースで動作します。場合によっては、待遇オブジェクト関数をコルーチン関数のように動作させるが、コルーチン関数ではない関数に渡すことがあります。 2つの例は、Futureクラスまたはフューチャーのようなオブジェクトクラス(クラスはimplements__await__
の魔法)です。この場合、iscoroutinefunction
はFalse
を返します。何が必要なのでしょうか?
それはコールバックとして非機能呼び出し可能なパッシングと非非同期例に理解することは簡単です:、
class SmartCallback:
def __init__(self):
print('SmartCallback is not function, but can be used as function')
await callCallback(SmartCallback) # Should work, right?
戻る非同期の世界に似たような状況:それをしませ解決する
class AsyncSmartCallback:
def __await__(self):
return self._coro().__await__()
async def _coro(self):
print('AsyncSmartCallback is not coroutine function, but can be used as coroutine function')
await asyncio.sleep(1)
await callCallback(AsyncSmartCallback) # Should work, but oops! iscoroutinefunction(AsyncSmartCallback) == False
ウェイiscoroutine
またはiscoroutinefunction
を使用しますが、代わりにinspect.isawaitable
を使用してください。準備ができているオブジェクトで動作するので、最初に作成する必要があります。言い換えれば、ソリューションを使用することをお勧めします:
async def callCallback(cb, arg):
if callable(cb):
res = cb() # here's result of regular func or awaitable
if inspect.isawaitable(res):
res = await res # await if awaitable
return res # return final result
else:
raise ValueError('cb is not callable')
これはより普遍的な(と私は確かに論理的に正しい)ソリューションです。
しかし、「真/偽」は「0」で割っています! :O – Shadow