Dependency Cache
Often, you will have dependencies that share a sub dependency.
For example, you probably only want to load your configuration from environment variables once and then re-use the same object in multiple dependencies.
To avoid re-computing the shared dependency, di
will cache shared dependencies.
How caching works
Dependencies are cached by their cache key, computed in Dependant.cache_key
.
See dependants for more information on Dependant.cache_key
.
Dependencies are cached by default, but this behavior can be changed on a per-dependency basis using the use_cache=False
parameter.
from random import random
from di import Container, Dependant, SyncExecutor
from di.typing import Annotated
def controller(
# no marker is equivalent to Dependant(object)
v1: object,
# the default value is use_cache=True
v2: Annotated[object, Dependant(object, scope="request")],
# but you can set use_cache=False
v3: Annotated[float, Dependant(random, use_cache=False, scope="request")],
) -> None:
assert v1 is v2
assert v1 is not v3 and v2 is not v3
def main() -> None:
container = Container(scopes=["request"])
solved = container.solve(Dependant(controller, scope="request"))
with container.enter_scope("request"):
container.execute_sync(solved, executor=SyncExecutor())
Caching and scopes
Dependencies are cached within their scope and any inner scopes. Once a dependency's scope exits, it's cached value is discarded and the next time the scope is entered a fresh value will be computed.