單例是設計模式中一個比較簡單但又比較重要的一個概念。今天讓我們來一起看一下,python中實現單例的幾種方法。
方案一:通過一個cahcemanager 來緩存類實例,這個是針對多個實例但是不重複的例子。
import weakref
class CacheManager:
def __init__(self):
self._cache = weakref.WeakValueDictionary()
def get_test(self, name):
if name not in self._cache:
temp = Test._new(name)
self._cache[name] = temp
else:
temp = self._cache[name]
return temp
class Test:
def __init__(self):
raise RuntimeError("Cannot instantiate directly")
@classmethod
def _new(cls, name):
self = cls.__new__(cls)
self.name = name
return self
def show(self):
print("The Test name is {0}".format(self.name))
if __name__ == "__main__":
cache = CacheManager()
test_abc = cache.get_test("abc")
test_abc.show()
test_abc2 = cache.get_test("abc")
if test_abc is test_abc2:
print("They are the same class")
方案二:使用類裝飾器, 真正的一個類只有一個實例。
from functools import wraps
def singleton(cls):
instance = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return wrapper
@singleton
class Test:
def __init__(self, name):
print("__init__")
self.name = name
def show(self):
print("The test name is {0}".format(self.name))
if __name__ == "__main__":
test1 = Test("abc")
test2 = Test("abc")
if test1 is test2:
print("They are the same class")
方案三:高端手法,使用元類。優雅實現方案一
import weakref
class Cached(type):
def __init__(cls, *args, **kwargs):
super().__init__(*args, **kwargs)
cls.__cached = weakref.WeakValueDictionary()
def __call__(cls, *args):
if args in cls.__cached:
return cls.__cached[args]
else:
obj = super().__call__(*args)
cls.__cached[args] = obj
return cls.__cached[args]
class Spam(metaclass=Cached):
def __init__(self, name):
print("Creating Spam")
self.name = name
if __name__ == "__main__":
a = Spam("Wang")
b = Spam("Wang")
if a is b:
print("They are the same class")