Why?
- There are many recipes but nearly all cover the global singleton only.
- I need a singleton which can handle things in a specific context (environment).
The final singleton is a combination of following two recipes:
The basic advantages:
- Hiding the singleton code by a simple decorator
- Flexible, because you can define fully global singletons or parameter based singletons.
Latest changes:
- Although a function/method does not have parameters you can call it with parameters args and kwargs as you now see in the getInstance function.
- ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | def singleton(theClass):
""" decorator for a class to make a singleton out of it """
classInstances = {}
def getInstance(*args, **kwargs):
""" creating or just return the one and only class instance.
The singleton depends on the parameters used in __init__ """
key = (theClass, args, str(kwargs))
if key not in classInstances:
classInstances[key] = theClass(*args, **kwargs)
return classInstances[key]
return getInstance
# Example
@singleton
class A:
""" test class """
def __init__(self, key=None, subkey=None):
self.key = key
self.subkey = subkey
def __repr__(self):
return "A(id=%d, %s,%s)" % (id(self), self.key, self.subkey)
def tests():
""" some basic tests """
testCases = [ (None, None), (10, 20), (30, None), (None, 30) ]
instances = set()
instance1 = None
instance2 = None
for key, subkey in testCases:
if key == None:
if subkey == None: instance1, instance2 = A(), A()
else: instance1, instance2 = A(subkey=subkey), A(subkey=subkey)
else:
if subkey == None: instance1, instance2 = A(key), A(key)
else: instance1, instance2 = A(key, subkey=subkey), A(key, subkey=subkey)
print("instance1: %-25s" % instance1, " instance2: %-25s" % instance2)
assert instance1 == instance2
assert instance1.key == key and instance1.subkey == subkey
instances.add(instance1)
assert len(instances) == len(testCases)
tests()
|
Tags: parameters, singleton