patternpythonMinor
Singleton Decorator
Viewed 0 times
decoratorsingletonstackoverflow
Problem
I've written a class that makes writing singletons easy. The class is meant to be used as a decorator (example below). I'd like to see your thoughts about the code, the documentation, and everything else that you feel is worth noting.
Now to test if the documentation was clear enough think about how you understood this class is meant to be used... Now look at this example and compare:
```
@Singleton
class Foo:
def __init__(self):
print('Foo created')
def bar(sel
class Singleton:
"""
Helper class meant to ease the creation of singletons. This
should be used as a decorator -- not a metaclass -- to the class
that should be a singleton.
The decorated class should define only one `__init__` function
that takes only the `self` argument. Other than that, there are
no restrictions that apply to the decorated class.
To get the singleton instance, use the `Instance` method. Trying
to use `__call__` will result in a `SingletonError` being raised.
"""
_singletons = dict()
def __init__(self, decorated):
self._decorated = decorated
def Instance(self):
"""
Returns the singleton instance. Upon its first call, it creates a
new instance of the decorated class and calls its `__init__` method.
On all subsequent calls, the already created instance is returned.
"""
key = self._decorated.__name__
try:
return Singleton._singletons[key]
except KeyError:
Singleton._singletons[key] = self._decorated()
return Singleton._singletons[key]
def __call__(self):
"""
Call method that raises an exception in order to prevent creation
of multiple instances of the singleton. The `Instance` method should
be used instead.
"""
raise SingletonError(
'Singletons must be accessed through the `Instance` method.')
class SingletonError(Exception):
passNow to test if the documentation was clear enough think about how you understood this class is meant to be used... Now look at this example and compare:
```
@Singleton
class Foo:
def __init__(self):
print('Foo created')
def bar(sel
Solution
It might be beneficial to add positional and keyword arguments to the
You may want to add methods to delete or redefine singletons if necessary or restructure your class to address naming conflicts. It breaks if you define one singleton and use it, then later redefine a new singleton using the same name.
Consider making
Consider using "new-style" class syntax explicitly.
__call__() method. That way you'll get your SingletonError for any call you attempt to make, rather than just the no-argument call.You may want to add methods to delete or redefine singletons if necessary or restructure your class to address naming conflicts. It breaks if you define one singleton and use it, then later redefine a new singleton using the same name.
Consider making
Instance a property rather than a method.Consider using "new-style" class syntax explicitly.
Context
StackExchange Code Review Q#4648, answer score: 3
Revisions (0)
No revisions yet.