gale.memoize module

This file contains Memoized (wraps a function, caching its return value per distinct positional/keyword argument combination) and the class Memo, a process-wide registry managing every Memoized created through Memo.memoize – the same shape gale.timer’s Timer manages Every/After/Tween: call Memo.update(dt) once a frame to age every registered cache.

A Memoized’s ttl decides what “cached” means, all driven by game time (dt) rather than the wall clock, so it pauses along with the rest of the game instead of expiring while a menu is open:

  • ttl=None (the default): cached forever, exactly like functools.lru_cache, until clear()/invalidate() is called explicitly. Prefer plain functools.lru_cache for this case unless you specifically want it to live in Memo’s registry (so Memo.clear() can drop it along with every ttl-based cache, on a level unload, say).

  • ttl=0: valid only for the remainder of the current frame – however many times it’s called before the next update(dt), the wrapped function runs once. Useful for a query several independent systems might ask for in the same frame (the nearest enemy, a pathfinding cost) without each paying for its own computation.

  • ttl=N (seconds): cached for up to N seconds of game time – useful for anything a game can afford to have go stale for a moment (an AI’s last line-of-sight check, a UI’s damage-number aggregation), trading a bit of staleness for not recomputing every single call. Unlike functools.lru_cache, entries actually expire, so decorating an instance method doesn’t pin that instance in memory forever.

See docs/examples/memoize.rst for a walkthrough.

Author: Alejandro Mujica (aledrums@gmail.com)

class gale.memoize.Memoized(function, ttl=None)[source]

Bases: object

Wraps a function, caching its return value per distinct positional/keyword argument combination. Usable directly (Memoized(fn)) or as a bare decorator (@Memoized); Memo.memoize builds one too, additionally registering it so Memo.update(dt) ages it automatically, and is the one that also accepts ttl as a decorator factory (@Memo.memoize(ttl=...)).

Parameters:
  • function (Callable[[...], Any])

  • ttl (float | None)

update(dt)[source]

Age every cached entry by dt, dropping whichever now exceed ttl. A no-op when ttl is None – a forever cache never expires.

Parameters:

dt (float)

Return type:

None

invalidate(*args, **kwargs)[source]

Drop the single cached entry for this exact call, if any.

Parameters:
  • args (Any)

  • kwargs (Any)

Return type:

None

clear()[source]

Drop every cached entry, forcing the next call for any arguments to recompute.

Return type:

None

class gale.memoize.Memo[source]

Bases: object

Process-wide registry of every Memoized created through Memo.memoize – call Memo.update(dt) once a frame to age all of them.

items: List[Memoized] = []
paused: bool = False
classmethod update(dt)[source]
Parameters:

dt (float)

Return type:

None

classmethod memoize(function=None, *, ttl=None)[source]
Parameters:
  • function (Callable[[...], Any] | None) – The function to wrap. When omitted, returns a decorator instead (@Memo.memoize(ttl=...)).

  • ttl (float | None) – Forwarded to Memoized. The default value is None.

Returns:

A Memoized already registered with this class, so Memo.update(dt)/pause()/resume()/clear() reach it.

classmethod clear()[source]
Return type:

None

classmethod pause()[source]
Return type:

None

classmethod resume()[source]
Return type:

None