本文目录导读:

在Python中实现单例模式有多种方式,以下是几种正确的实现方法,按推荐程度排序:
使用模块(最Pythonic的方式)
Python模块天然是单例的,因为模块在第一次导入时被加载一次:
# singleton_module.py
class SingletonClass:
def __init__(self):
self.value = None
def do_something(self):
return "Singleton method"
# 创建全局实例
singleton = SingletonClass()
# 使用 from singleton_module import singleton singleton.value = 42
使用元类(最正统的方式)
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
def __init__(self):
self.value = None
# 使用
s1 = Singleton()
s2 = Singleton()
assert s1 is s2 # True
使用装饰器(简洁优雅)
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
self.connection = None
# 使用
db1 = Database()
db2 = Database()
assert db1 is db2 # True
使用new方法(最直接)
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if not self._initialized:
self._initialized = True
# 初始化代码,只执行一次
self.value = None
# 使用
s1 = Singleton()
s2 = Singleton()
assert s1 is s2 # True
线程安全的实现
import threading
class ThreadSafeSingleton:
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if not self._initialized:
self._initialized = True
self.value = None
# 使用
s1 = ThreadSafeSingleton()
s2 = ThreadSafeSingleton()
assert s1 is s2 # True
推荐方案
- 项目简单:使用模块方式,简单直接
- 需要继承:使用元类方式,最正统
- 需要单例/非单例切换:使用装饰器方式
- 多线程环境:使用线程安全实现
注意事项
# 错误的实现
class BadSingleton:
_instance = None
def __init__(self):
# 每次调用都会执行,会覆盖已有状态
self.value = None
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
# 这种实现的问题:
# 1. 直接调用 BadSingleton() 会创建新实例
# 2. 必须使用 get_instance() 方法才能获取单例
选择哪种方式取决于具体需求,模块方式是最Pythonic且最简单的选择。