共计 1184 个字符,预计需要花费 3 分钟才能阅读完成。
首先,我们先创建一个测试用例
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 |
你也可以使用装饰器,个人感觉和元类差不多,但是元类更优雅。这里就不展示装饰器的用法了。
正文完