Python Class Inherited Singleton Inits Instance On Every Call
Solution 1:
In modern Python this could be done by writting a __init_subclass__
method that could decorate __init__
to make it check cls._instance
before running.
As it is, (i.e. you need it for Python 2 as well) - I think the simpler thing is for __new__
to patch __init__
with a NOP method if the instance already exists:
_nop_init = lambda self, *args, **kw: NoneclassSingleton(object):
_instance = Nonedef__new__(cls, *args, **kwargs):
ifnotisinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
cls._instance._initialized = False# Python 2 have to check in the cls.__dict__ - Py3 could check the attribute directly:elif cls.__dict__.get("__init__", None) isnot _nop_init:
cls.__init__ = _nop_init
return cls._instance
classA(Singleton):
def__init__(self):
print"Init is called"classB(Singleton):
def__init__(self):
print"Init is called"
extra info The language mechanism to call __init__
is built-in the __call__
method of type
- the metaclass for all classes in Python. It will call the __new__
and __init__
method of a target class when instantiating it, and thus, with a metaclass, it is easy to control these calls from a custom metaclass. It is also interesting to note that when __new__
does not return an instance of the target class, __init__
is not called. (In this singleton case, the singleton is an instance of te class, and thus it is called).
real world example: last time I coded a singleton, I opted for avoiding re-run __init__
in its own code - sine it is the only singleton in the project, tere was no need for generic code for that in a __new__
:
https://github.com/jsbueno/pythonchain/blob/1f9208dc8bd2741a574adc1bf745d218e4314e4a/pythonchain/block.py#L276
Post a Comment for "Python Class Inherited Singleton Inits Instance On Every Call"