Singleton¶
Support for fast, memory efficient singleton objects.
Why is this here? The externalization system can use lots of objects as it goes through its process. Many of those objects are adapters (for example, the decorator objectes), meaning a factory callable is called to (create and) return an object (given a particular context, and possibly request).
But the API of many adapter objects accept all the information they need to have in the functions defined in the interface. That is, the constructor does nothing useful with the context (and request). The objects are stateless, and so constructing a new one for each adapter invocation can be a waste of time and memory.
By either using the SingletonMetaclass
as your metaclass, or
subclassing Singleton
, that cost is paid only once, replacing a call
to a constructor and an object allocation with a faster call to return
a constant object.
-
class
SingletonMetaclass
[source]¶ Bases:
type
Metaclass for singleton classes most commonly used as external object decorators (adapters). These objects accept one or two context arguments to their
__init__
function, but they do not actually use them (because the same object is passed to their decoration method). Thus they can usefully be constructed just once and shared. This metaclass ensures the singleton property, ensures that the__init__
method is a no-op, and ensures that the instance has no dictionary or instance variable.A singleton class has only one instance which is returned every time the class is instantiated.
Caution
We cannot be used with
six.with_metaclass()
because it introduces temporary classes. You’ll need to use the metaclass constructor directly:AClass = SingletonMetaclass('AClass', (object,), {})
Alternatively, you can inherit from
Singleton
.Implementation Notes
The class is instantiated immediately at the point where it is defined by calling
cls.__new__(cls)
. This instance is cached andcls.__new__
is rebound to return it directly.The original constructor is also cached to allow subclasses to access it and have their own instance.
>>> from nti.externalization.singleton import Singleton >>> class TopSingleton(Singleton): ... def __init__(self): ... print("I am never called") >>> inst = TopSingleton() >>> isinstance(inst, TopSingleton) True >>> TopSingleton() is inst True >>> class DerivedSingelton(TopSingleton): ... pass >>> derived = DerivedSingelton() >>> isinstance(derived, DerivedSingelton) True >>> DerivedSingelton() is derived True >>> derived is inst False