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 and cls.__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
class Singleton

Bases: object

A base class for singletons. Can be more convenient than a metaclass for Python2/Python3 compatibility.