python的两种单例模式

基于模块的单例模式

在 Python 中,模块是天然的单例模式。因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,会直接加载 .pyc 文件,而不会再次执行模块代码。因此,可以将相关的类和实例定义在一个模块中,通过导入模块来获取唯一的实例。

py 复制代码
# singleton_module.py
class SingletonClass:
    def __init__(self):
        self.value = 0

    def increment(self):
        self.value += 1

# 创建唯一的实例
singleton_instance = SingletonClass()

然后在另一个文件中使用这个单例实例:

py 复制代码
# main.py
from singleton_module import singleton_instance

# 第一次调用
print(singleton_instance.value)  # 输出 0
singleton_instance.increment()

# 再次调用
from singleton_module import singleton_instance
print(singleton_instance.value)  # 输出 1

在 singleton_module.py 中定义了一个 SingletonClass 类,并创建了该类的一个实例 singleton_instance

在 main.py 中,无论导入多少次 singleton_instance,获取的都是同一个实例,因此对实例的操作会保持状态

基于装饰器的单例模式

使用装饰器可以在不修改原类代码的情况下,将类转换为单例类。装饰器会维护一个字典,用于存储类和其对应的实例,当第一次调用被装饰的类创建实例时,会将该实例存储在字典中,后续再次调用时,直接从字典中获取已创建的实例。

py 复制代码
# 入参是一个类,出参是一个函数
def singleton_decorator(cls):
    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return get_instance

@singleton_decorator
class MySingleton:
    def __init__(self):
        self.value = 0

    def increment(self):
        self.value += 1

# 创建实例
instance1 = MySingleton()
instance2 = MySingleton()

print(instance1 is instance2)  # 输出 True,表示两个实例是同一个对象
instance1.increment()
print(instance2.value)  # 输出 1

代码解释

singleton_decorator 是一个装饰器函数,它接受一个类作为参数,并返回一个 get_instance 函数

instances 是一个字典,用于存储类和其对应的实例

get_instance 函数会检查 instances 字典中是否已经存在该类的实例,如果不存在则创建一个新实例并存储在字典中,然后返回该实例。

MySingleton 类被 singleton_decorator 装饰

每次创建 MySingleton 类的实例时,实际上都会返回同一个实例

优缺点

基于模块的方式简单直接,适合简单场景

基于装饰器的方式更加灵活,可以应用于多个不同的类

相关推荐
java_prinln9 小时前
RAG 面试题介绍
python·agent
威哥爱编程9 小时前
Python 智能体开发实战 06:一个函数里塞了八百行?用状态机把批改流程拆成能回退的步骤
python·agent
Patrick在香港9 小时前
一个斜杠,把毫秒变成十几秒
android·数据库·python·性能优化·正则表达式·回溯·redos
2601_9679801110 小时前
Python 初学者必备的常用内置函数
python·编程语言·内置函数·初学者·常用函数
OnlineProxy10 小时前
移动应用数据爬取:通过模拟器与流量嗅探对 API 进行逆向工程
爬虫·python·httpx
染指111010 小时前
162.Agent-LangGraph-检查点的作用
人工智能·python·langchain·agents
我命由我1234510 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
xixingzhe210 小时前
图表中同比与环比的区别:看趋势还是看变化?
开发语言·python
forest_0911 小时前
当 AI 搜索开始「自我进化」,谁来进化它的核实?——「已核实」结论复核器:3 条结论挖出 2 个洞(附可运行代码)
人工智能·python·机器学习·prompt·agi
小小张说故事11 小时前
Python 的 str 为什么设计成不可变?拆开字符串驻留、字符串池,以及 += 拼接到底慢在哪
后端·python