Skip to content

Instantly share code, notes, and snippets.

@ask
Last active February 28, 2018 11:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ask/e2a70efd6556ecaa400aabe220f8434f to your computer and use it in GitHub Desktop.
Save ask/e2a70efd6556ecaa400aabe220f8434f to your computer and use it in GitHub Desktop.
async_cached_property
import asyncio
from typing import Any, Awaitable, Callable, Optional, Type
# eh, like the @cached_property idiom, but async and you do `await x.y`
class async_cached_property:
name: str
def __init__(self, getter: Callable[[], Awaitable]) -> None:
self._getter = getter
self.name = self._getter.__name__
def __get__(self, instance: Optional[Any], cls: Type) -> Awaitable:
if instance is None:
return self
try:
followers_future = instance.__dict__[self.name]
return followers_future
except KeyError:
followers_future = instance.__dict__[self.name] = asyncio.Future()
winners_future = asyncio.ensure_future(self._getter(instance))
winners_future.add_done_callback(
lambda fut: followers_future.set_result(fut.result()))
return winners_future
class X:
@async_cached_property
async def y(self) -> float:
await asyncio.sleep(1.0)
return 1.0
async def test():
x = X()
print(await x.y)
for i in range(100):
print(await x.y)
if __name__ == '__main__':
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(test())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment