hashcons.instance_store
The InstanceStore class provides a mechanism to manage the creation
of instances for flyweight classes, based on class and a unique instance key.
InstanceStore
- class InstanceStore[source]
Bases:
objectAn instance store, which can be used to manage the process of instance creation for instances of flyweight classes. Instances are stored internally in a
WeakValueDictionary, indexed by their class and a user-provided instance key.The
instancemethod implements a context manager for use within the flyweight class constructor, within which managed instance creation can be performed.The
registermethod must be called within theinstancecontext when a new instance is created, as opposed to when an existing instance is used.class MyClass: __store: ClassVar[InstanceStore] = InstanceStore() def __new__(cls, ...) -> Self: # args ^^^ key = ...# derive instance key from constructor args with MyClass.__store.instance(cls, key) as self: if self is None: # if no instance with given key exists self = super().__new__(cls) ... # <- set instance attributes here MyClass.__store.register(self) return self ... # <- class body here
In order to customise the instance creation process, it will typically be necessary to implement flyweight class constructors using __new__, rather than __init__.
If pickle <https://docs.python.org/3/library/pickle.html> support is desirable, flyweight classes should implement either the __getnewargs__ method or the __getnewargs_ex__ method, depending on whether the constructor takes keyword-only arguments. Classes should also implement __getstate__ <https://docs.python.org/3/library/pickle.html#object.__getstate__>`_ to return
None, in order to prevent the default __setstate__ <https://docs.python.org/3/library/pickle.html#object.__setstate__>`_ being called by the pickling process (cf. PEP 307).def __getnewargs__(self) -> tuple[...]: # __new__ arg types here ^^^ return (...) # ^^^ args to __new__ here def __getstate__(self) -> Literal[None]: return None
- get(cls, key)[source]
Returns the instance with given class and instance key, or
Noneif no such instance exists.
- instance(cls, key)[source]
Context manager to manage the creation of an instance of the given class, uniquely identified by the given key.
If an instance with the given key already exists, it is yielded. Otherwise, the following procedure is followed:
The instance building process is started.
The value
Noneis yielded, to signal to the context that no instance with the given key exists yet.Once control is returned to the context manager, it checks that an instance was registered using the :meth`register` method, and that it is actually an instance of the given class.
If the checks from Step 3 are successful, the instance is stored using the given class and key.
Regardless of whether the checks from Step 3 are successful, the instance building process is terminated.
It is possible for the same instance building process to be shared by multiple contexts, e.g. when using the same store for instances of a class and its subclasses. If the context manager is invoked multiple times, it yields the same value across all calls, but the instance process is started at most once by the outermost call, and fully handled by it. This makes it possible to create subclasses of a flyweight class.
If the instance building process is started, the
registermethod must be called exactly once.Failure to comply with the above requirements results in an
AssertionErrorbeing raised. For the sake of performance, all validation is done by assertions, so it is removed when compiling with the -O flag.
- register(instance)[source]
If the instance building process is active, the given instance is registered as the fresh instance being built. Otherwise, the instance is ignored.
If the instance building process is started by the
instancemethod, theregistermethod must be called exactly once, otherwise anAssertionErrorwill be raised by theinstancemethod at the moment when the context is exited.
T_co
- T_co = +T_co
Covariant type variable for arbitrary values.