How to decorate a class in the right way to be able to inherit a classes from the decorated one? Is there exists a right way?
If I will do something like:
def singleton(cls):
inst = {}
def get(*args, **kwargs):
cls_id = id(cls)
if cls_id not in inst:
inst[cls_id] = cls(*args, **kwargs)
return inst[cls_id]
return get
@singleton
class A(object):
@classmethod
def cls_meth(cls):
return cls
I have no chance to inherit a class from above one, because before I call it this is the function. The same problem with classmethods, function have no classmethods.
class B(A): # No way! `A` is the function!
pass
A.cls_meth() # AttributeError: 'function' object has no attribute 'cls_meth'
Even I doing something like:
class SingletonDecorator(object):
inst = {}
def __init__(self, cls):
self.cls = cls
def __call__(self, *args, **kwargs):
cls_id = id(self.cls)
if cls_id not in self.inst:
self.inst[cls_id] = self.cls(*args, **kwargs)
return self.inst[cls_id]
@SingletonDecorator
class A(object):
pass
When I inherit a class from A
class, it will be inherited from SingletonDecorator
class instead of A
.
class B(A): # No no no! I do not need a `SingletonDecorator` child class...
pass
There is a way to modify class instance via __metaclass__
, but but that is absolutely another story...
Your decorator needs to return the original class (or a subclass of it) to be able to subclass it further. Your decorator returns an instance of itself when used as a decorator (because that's the default behavior of calling a class).
For example, something like this:
def singleton(cls):
class C(cls):
_instance = None
def __new__(c, *args, **kwargs):
if type(c._instance) != c:
c._instance = cls.__new__(c, *args, **kwargs)
return c._instance
C.__name__ = cls.__name__
return C
This returns a subclass of the original class with an overridden __new__()
method that does the singleton magic. This class is subclassable.
There is almost never any reason to create a singleton, however. Often it's just a way of hiding global state that would be better eliminated.