首先,咱們先建立一個測試用例python
def test_sig(sig_class): a = sig_class(1) print("a = {}(1)\na.value={}".format(sig_class.__name__, a.value)) b = sig_class(2) print("b = {}(2)\nb.value={}".format(sig_class.__name__, b.value)) print("Now a.value={}".format(a.value)) print("a is b: {}".format(a is b))
class Singletone(): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: # 注意,這裏的__new__不接受參數 # 參考: https://stackoverflow.com/questions/34777773 cls._instance = super().__new__(cls) return cls._instance return cls._instance def __init__(self, n): self.value = n test_sig(Singletone)
輸出以下:測試
a = Singletone(1) a.value=1 b = Singletone(2) b.value=2 Now a.value=2 a is b: True
在py3.3後,若是同時建立__init__
和__new__
,__new__
裏,就不要再傳參數了。不然就會TypeError: object() takes no parameters
code
class Single(type): # 這裏建立了一個Single元類, # 注意這裏使用一個字典,而不是直接用一個None值, # 這樣,任何使用該元類的子類,都將是單例模式,並且互不污染 _instances = {} def __call__(cls, *args, **kwargs): if not cls._instances: # 注意,這裏使用的是__call__語句,與__new__不一樣,傳入的參數也不一樣。 cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class Singletone2(metaclass=Single): def __init__(self, n): self.value = n test_sig(Singletone2)
輸出以下:orm
a = Singletone2(1) a.value=1 b = Singletone2(2) b.value=1 Now a.value=1 a is b: True
你也能夠使用裝飾器,我的感受和元類差很少,可是元類更優雅。這裏就不展現裝飾器的用法了。it