I have come across this singleton implementation here: http://blog.amir.rachum.com/post/21850841339/implementing-the-singleton-pattern-in-python in the first reply.
def singleton(cls):
return cls()
@singleton
class Foo(object):
def bar(self):
pass
if __name__ == '__main__':
print id(Foo)
print id(Foo)
But I don't understand the inner workings, the decorator returns a class instance, but why the same instance every time ?
You can rewrite that code to
class Foo(object):
pass
Foo = singleton(Foo)
# which is
Foo = Foo()
So here the name of the class is replaced by an instantiation of it. A bit cheesy in my opinion, especially since you can still create new objects of the same class by using Foo.__class__ and you are messing with the naming schema.
The singleton does that by holding internal state. This state here would probably be an instance of the class. The decorator can be something arbitrary.
Have a look at this:
http://hairysun.com/downloads/DecoratorHandout.pdf
class Decorator(object):
# in __init__ set up state
def __call__(self, function):
@functools.wraps(function)
def wrapper(*args, **kw): # 1.
print "before func"
result = function(*args, **kw) # 2.
print "after func"
return result
return wrapper # 3.
>>> decorator2 = Decorator()
>>> @decorator2
... def nothing(): pass
The decorator is essentially a function that
The surrounding class (here: the decorator) could do something like this:
class Singleton(object):
def __init__(self):
self.instance = None
def __call__(self, function):
@functools.wraps(function)
def wrapper(*args, **kw):
if self.instance is None:
self.instance = function(*args, **kw)
return self.instance
return wrapper
I did not run the code, but I assume this is in general how it works. If there is no instance available create one. If one is available, don't create a new one - return the single old one instead. One might probably want to check for other properties of the callable before using this in production.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With