单例模式 #
单例模式确保一个类只有一个实例,多次初始化返回同一个实例。可以使用类装饰器或元类实现
from functools import wraps
def singleton(cls):
"""单例类装饰器"""
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo():
pass
# @singleton 等价于 Foo = singleton(Foo)
print(type(Foo)) # <class 'function'>,为wrapper函数,而不是Foo类
# 由于类本身是可调用的对象,返回一个函数来替代类在调用时的行为是可行的,wrapper函数提供了与类构造行为相同的逻辑
# 更本质的是:Foo() 其实就等价于 wrapper.__call__()
f1 = Foo()
f2 = Foo()
print(f1 is f2) # True
import threading
class SingletonMeta(type):
_instances = {}
_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
# cls 为 Foo 类
# Foo 类 为 SingletonMeta 的实例,类的实例可以访问到类属性,所以可以访问到 _instances 和 _lock
with cls._lock:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Foo(metaclass=SingletonMeta):
pass
f1 = Foo()
f2 = Foo()
print(f1 is f2) # True