Python脚本单例模式如何正确实现

wen 实用脚本 12

本文目录导读:

Python脚本单例模式如何正确实现

  1. 使用模块(最Pythonic的方式)
  2. 使用元类(最正统的方式)
  3. 使用装饰器(简洁优雅)
  4. 使用new方法(最直接)
  5. 线程安全的实现
  6. 推荐方案
  7. 注意事项

在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

推荐方案

  1. 项目简单:使用模块方式,简单直接
  2. 需要继承:使用元类方式,最正统
  3. 需要单例/非单例切换:使用装饰器方式
  4. 多线程环境:使用线程安全实现

注意事项

# 错误的实现
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且最简单的选择。

抱歉,评论功能暂时关闭!