Decorator for creating a singleton class
Description:
- Decorate a class with this decorator
- If you happen to create another instance of the same class, it will
return the previously created one
- Supports creation of multiple instances of same class with different
args/kwargs
- Works for multiple classes
- Multithreading supported
Use:
>>> import singleton
>>>
>>> @singleton
... class A:
... def init(self, args, *kwargs):
... pass
>>>
>>> obj1 = A(name='Mary')
>>> obj2 = A(name='Mary', lname='Brown')
>>> obj3 = A(name='Mary', lname='Brown')
>>> obj1 is obj2 # has to be different
False
>>> obj2 is obj3 # has to be same
True
>>>
Source code in singleton.py
| def singleton(cls: Callable[..., T]) -> Callable[..., T]:
"""
Decorator for creating a singleton class
Description:
- Decorate a class with this decorator
- If you happen to create another instance of the same class, it will
return the previously created one
- Supports creation of multiple instances of same class with different
args/kwargs
- Works for multiple classes
- Multithreading supported
Use:
>>> import singleton
>>>
>>> @singleton
... class A:
... def __init__(self, *args, **kwargs):
... pass
>>>
>>> obj1 = A(name='Mary')
>>> obj2 = A(name='Mary', lname='Brown')
>>> obj3 = A(name='Mary', lname='Brown')
>>> obj1 is obj2 # has to be different
False
>>> obj2 is obj3 # has to be same
True
>>>
"""
previous_instances = {}
lock = threading.RLock()
@functools.wraps(cls)
def wrapper(*args, **kwargs) -> T:
"""
Wrapper function for singleton decorator
:param args: args to be passed to the class
:param kwargs: kwargs to be passed to the class
:return: instance of the class
"""
with lock:
if cls in previous_instances:
if previous_instances.get(cls).get('args') == (args, kwargs):
return previous_instances[cls].get('instance')
previous_instances[cls] = {'args': (args, kwargs),
'instance': cls(*args, **kwargs)}
return previous_instances[cls].get('instance')
return wrapper
|