The functools library¶
The asyncstdlib.functools
library implements
Python’s functools
for (async) functions and (async) iterables.
Iterator reducing¶
- await reduce(function: (T, T) → (await) T, iterable: (async) iter T, initial: T) T [source]¶
Reduce an (async) iterable by cumulative application of an (async) function
- Raises
TypeError – if
iterable
is empty andinitial
is not given
Applies the
function
from the beginning ofiterable
, as if executingawait function(current, anext(iterable))
untiliterable
is exhausted. Note that the output offunction
should be valid as its first input.The optional
initial
is prepended to all items ofiterable
when applyingfunction
. If the combination ofinitial
anditerable
contains exactly one item, it is returned without callingfunction
.
Async Caches¶
The regular functools.lru_cache()
and functools.cached_property()
are not appropriate for
async callables, such as an async def
coroutine function:
their direct return value is an awaitable instead of the desired value.
This causes the cache to store only temporary helpers, not the actual values.
Both lru_cache()
and cached_property()
of asyncstdlib
work only with async callables
(they are not async neutral).
Notably, this includes regular callables that return an awaitable,
such as an async def
function wrapped by partial()
.
- @cached_property(getter: (Self) → await T)¶
Transform a method into an attribute whose value is cached
When applied to an asynchronous method of a class, instances have an attribute of the same name as the method (similar to
property
). Using this attribute withawait
provides the value of using the method withawait
.The attribute value is cached on the instance after being computed; subsequent uses of the attribute with
await
provide the cached value, without executing the method again. The cached value can be cleared usingdel
, in which case the next access will recompute the value using the wrapped method.import asyncstdlib as a class Resource: def __init__(self, url): self.url = url @a.cached_property async def data(self): return await asynclib.get(self.url) resource = Resource(1, 3) print(await resource.data) # needs some time... print(await resource.data) # finishes instantly del resource.data print(await resource.data) # needs some time...
Unlike a
property
, this type does not supportsetter()
ordeleter()
.Note
Instances on which a value is to be cached must have a
__dict__
attribute that is a mutable mapping.New in version 1.1.0.
The lru_cache()
can be applied as a decorator, both with and without arguments:
@a.lru_cache
async def get_pep(num):
url = f'http://www.python.org/dev/peps/pep-{num:04}/'
request = await asynclib.get(url)
return request.body()
@a.lru_cache(maxsize=32)
async def get_pep(num):
url = f'http://www.python.org/dev/peps/pep-{num:04}/'
request = await asynclib.get(url)
return request.body()
- @cache((...) -> await R)[source]¶
Simple unbounded cache, aka memoization, for async functions
This is a convenience function, equivalent to
lru_cache()
with amaxsize
ofNone
.New in version 3.9.0.
- @lru_cache(maxsize: ?int = 128, typed: bool = False)((...) -> await R)¶
Least Recently Used cache for async functions
Applies an LRU cache, mapping the most recent function call arguments to the awaited function return value. This makes this cache appropriate for coroutine functions,
partial()
coroutines and any other callable that returns an awaitable.Arguments to the cached function must be hashable. On a successful cache hit, the underlying function is not called. This means any side-effects, including scheduling in an internal event loop, are skipped. Ideally,
lru_cache
is used for long-running queries or requests that return the same result for the same input.The maximum number of cached items is defined by
maxsize
:If set to a positive integer, at most
maxsize
distinct function argument patterns are stored; further calls with different patterns evict the oldest stored pattern from the cache.If set to zero or a negative integer, the cache is disabled. Every call is directly forwarded to the underlying function, and counted as a cache miss.
If set to
None
, the cache has unlimited size. Every new function argument pattern adds an entry to the cache; patterns and values are never automatically evicted.
The cache can always be explicitly emptied via
cache_clear()
. Use the cache’scache_info()
to inspect the cache’s performance and filling level.If
typed
isTrue
, values in argument patterns are compared by value and type. For example, this means that passing3
and3.0
as the same argument are treated as distinct pattern elements.Note
This wrapper is intended for use with a single event loop, and supports overlapping concurrent calls. Unlike the original
functools.lru_cache()
, it is not thread-safe.
The cache tracks call argument patterns and maps them to observed return values.
A pattern is an ordered representation of provided positional and keyword arguments;
notably, this disregards default arguments, as well as any overlap between
positional and keyword arguments.
This means that for a function f(a, b)
, the calls f(1, 2)
, f(a=1, b=2)
and f(b=2, a=1)
are considered three distinct patterns.
In addition, exceptions are not return values. This allows retrying a long-running query that may fail, caching any eventual result for quick and reliable lookup.
A wrapped async callable can be queried for its cache metadata,
and allows clearing the entire cache. This can be useful to explicitly monitor
cache performance, and to manage caches of unrestricted size.
Note that the maxsize
of a cache cannot be changed at runtime – however,
the __wrapped__
callable may be wrapped with a new cache of different size.
- class LRUAsyncCallable¶
Protocol
of a LRU cache wrapping a callable to an awaitable- __wrapped__¶
The callable wrapped by this cache
- await __call__(...) await R [source]¶
Get the result of
await __wrapped__(...)
from the cache or evaluation
- cache_info() -> (hits=..., misses=..., maxsize=..., currsize=...)[source]¶
Get the current performance and boundary of the cache as a
NamedTuple
New in version 3.9.0: The
cache_parameters()
method.