Simple as it may seem, I've ended with two part blog post series on the subject. This part talks about decorator approach and the next part talks about classmethod approach. Enjoy.
Decorator approach
Stackoverflow hinted a decorator approach, but that example breaks Python object model. Particularly, considering:
def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass(object): pass
Then the following would reasonably fail:
c = MyClass() isinstance(c, MyClass) TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and typesSince in fact after decoration
MyClass
is a function and not a class.
To fix this, we'll rewrite decorator to return class instead. And to make sure that inheritance check works, we'll inherit from decorated class during decoration process.
def SingletonClass(cls): class Single(cls): __doc__ = cls.__doc__ _initialized = False _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Single, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self, *args, **kwargs): if self._initialized: return super(Single, self).__init__(*args, **kwargs) self.__class__._initialized = True return Single @SingletonClass class MyClass(object): passNow
isinstance
does the right thing:
>>> c = MyClass() >>> isinstance(c, MyClass) True
We are sort of double-cheating here, since even c.__class__ == MyClass
is true. I say cheating because both of them are actually <class 'Single'>
and original MyClass
class is lost during decoration.
And a final touch is to copy a doc string of course :)
No comments:
Post a Comment