首先,我們先創建一個測試用例
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))
__new__ 方法
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
元類
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)
輸出如下:
a = Singletone2(1)
a.value=1
b = Singletone2(2)
b.value=1
Now a.value=1
a is b: True
你也可以使用裝飾器,個人感覺和元類差不多,但是元類更優雅。這裏就不展示裝飾器的用法了。