0

0

python中怎么实现单例模式_Python设计模式之单例模式实现

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-09-14 23:10:01

|

808人浏览过

|

来源于php中文网

原创

Python中实现单例模式的常见方法有:1. 重写__new__方法,通过类属性控制实例唯一性,适合简单场景;2. 使用装饰器,将单例逻辑与业务类分离,提升代码可读性和复用性;3. 利用元类(Metaclass),在类创建阶段控制实例化过程,适用于框架级设计。这些方法中,__new__方式最直接,装饰器更“Pythonic”,元类则提供更强的控制力。实际应用中,单例常用于配置管理器、日志记录器、数据库连接池等需要全局唯一、共享状态的组件。为保证线程安全,应使用threading.Lock结合双重检查锁定机制,防止多线程环境下生成多个实例,同时通过标志位确保__init__仅执行一次。

python中怎么实现单例模式_python设计模式之单例模式实现

在Python中实现单例模式,最直接且常用的方式是重写类的

__new__
方法,确保每次实例化时都返回同一个对象实例。更优雅一点,也可以考虑使用装饰器或元类,它们能让单例逻辑与业务代码分离,保持代码的整洁性。

直接输出解决方案:

import threading

class Singleton(object):
    _instance = None
    _lock = threading.Lock() # 用于线程安全

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock: # 双重检查锁定,确保在锁定后再次检查
                if not cls._instance:
                    cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

# 示例使用
# class MyConfig(Singleton):
#     def __init__(self, setting):
#         if not hasattr(self, '_initialized'): # 确保__init__只执行一次
#             self.setting = setting
#             self._initialized = True
#
# config1 = MyConfig("Database Settings")
# config2 = MyConfig("Another Setting")
#
# print(config1 is config2) # True
# print(config1.setting) # Database Settings
# print(config2.setting) # Database Settings (still "Database Settings" as __init__ only ran once for the first instance)
#
# config3 = MyConfig("New Setting") # 再次尝试创建,__init__不会再执行,因为_initialized已为True
# print(config3.setting) # 仍然是 Database Settings

Python中实现单例模式的几种常见方法有哪些? 在我看来,Python实现单例模式的方式有那么几种,每种都有其适用场景和一些小小的“癖好”。最常见的,也是我个人觉得最直观的,就是通过重写

__new__
方法。当你创建一个类的实例时,
__new__
方法总是在
__init__
之前被调用,它负责创建并返回新的对象实例。所以,我们可以在这里做文章,判断是否已经有实例存在,有就直接返回,没有就创建一个。这种方式的优点是简单直接,容易理解,而且可以很自然地处理
__init__
只执行一次的问题(通常需要加一个标志位来控制)。

不过,如果你想让单例的逻辑更“透明”,不侵入到业务类本身,那么装饰器(Decorator)就是个不错的选择。你可以写一个通用的单例装饰器,然后把任何需要变成单例的类都用它装饰一下。这样,类的定义本身就保持了纯粹,单例的职责被外部化了。我通常会觉得这种方式更“Pythonic”一些,因为它利用了Python的函数式编程特性。

还有一种更高级、更强大的方法,就是使用元类(Metaclass)。元类是创建类的类,听起来有点绕,但它能让你在类创建的时候就介入,从而实现更深层次的控制。用元类实现单例,意味着所有由这个元类创建的类,都会自动拥有单例的特性。这对于构建框架或者需要对大量类强制执行某种行为时非常有用。缺点嘛,就是概念上相对复杂一些,对初学者来说可能有点门槛。

立即学习Python免费学习笔记(深入)”;

总结一下,

__new__
适合快速实现;装饰器适合保持业务类整洁;元类适合框架级或需要广泛应用单例行为的场景。我个人在日常开发中,如果不是特别复杂的场景,通常会倾向于
__new__
或装饰器,因为它们在理解和维护上成本较低。

Python单例模式在实际项目中有哪些应用场景? 单例模式在实际项目中的应用场景其实挺多的,虽然有时候它也会被过度使用或误用。我个人觉得,它最闪光的几个地方在于那些“全局唯一”且“状态共享”的组件。

比如,配置管理器(Configuration Manager)。一个应用程序通常只有一套配置,比如数据库连接字符串、API密钥等。如果每次需要配置信息都去加载一次,或者创建新的配置对象,那效率和一致性都会出问题。这时候,把配置管理器做成单例,确保所有地方都访问同一个配置实例,就显得非常合理和方便。

日志记录器(Logger)也是一个经典案例。整个应用可能需要将日志输出到同一个文件或同一个日志服务。如果每个模块都创建自己的日志实例,不仅资源浪费,还可能导致日志顺序混乱或文件句柄冲突。一个全局的单例日志器就能很好地解决这个问题,它集中管理日志输出,确保日志流的一致性和效率。

迷你天猫商城
迷你天猫商城

迷你天猫商城是一个基于Spring Boot的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程:用户从注册开始,到完成登录,浏览商品,加入购物车,进行下单,确认收货,评价等一系列操作。 作为迷你天猫商城的核心组成部分之一,天猫数据管理后台包含商品管理,订单管理,类别管理,用户管理和交易额统计等模块,实现了对整个商城的一站式管理和维护。所有页面均兼容IE10及以上现代浏览器。部署方式1、项目

下载

再比如,数据库连接池(Database Connection Pool)。管理数据库连接是资源密集型操作,频繁地创建和关闭连接会严重影响性能。通常我们会维护一个连接池,所有需要数据库操作的地方都从这个池子里获取连接。这个连接池自然应该是一个单例,确保所有请求共享同一个连接资源池,从而优化性能和资源利用。

还有一些我遇到过的,比如任务调度器(Task Scheduler),整个系统可能只有一个主调度器来管理各种定时任务;或者一些缓存服务(Cache Service),为了保证缓存数据的一致性,也常被设计成单例。这些场景的共同特点是:它们代表了某种全局的、唯一的资源或服务,需要被所有组件共享和协调。

Python实现单例模式时如何处理线程安全问题? 谈到单例模式,线程安全绝对是一个绕不开的话题,尤其是在多线程的Python应用中。如果没有妥善处理,你可能会在并发环境下创建出多个“单例”实例,那单例的意义就完全丧失了。我遇到过几次因为没有考虑线程安全而导致的奇怪bug,排查起来还挺费劲的。

核心问题在于,当多个线程几乎同时判断

_instance
None
时,它们都可能尝试去创建实例。为了避免这种竞态条件(Race Condition),我们需要引入锁机制。Python标准库中的
threading
模块提供了
Lock
对象,可以用来保护临界区代码。

最常见的做法是使用“双重检查锁定”(Double-Checked Locking)。它的思路是,首先在不加锁的情况下检查

_instance
是否存在。如果不存在,才去获取锁。获取锁之后,再次检查
_instance
是否存在。为什么要检查两次呢?因为在第一个线程获取锁并创建实例的过程中,可能有其他线程已经通过了第一次
_instance
None
的检查,正在等待锁。当第一个线程释放锁后,这些等待的线程会依次获得锁,如果没有第二次检查,它们会再次创建实例。

所以,一个线程安全的单例实现会像我前面给出的代码示例那样:

import threading

class Singleton(object):
    _instance = None
    _lock = threading.Lock() # 初始化一个线程锁

    def __new__(cls, *args, **kwargs):
        if not cls._instance: # 第一次检查 (不加锁)
            with cls._lock: # 获取锁,进入临界区
                if not cls._instance: # 第二次检查 (加锁后)
                    cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

通过

with cls._lock:
语句,我们确保了在同一时间只有一个线程能够执行
_instance = super(Singleton, cls).__new__(cls)
这行代码。这样,即使在高并发环境下,也能保证
_instance
只会被创建一次。这是一个非常实用且可靠的模式,在很多并发编程场景下都有应用。当然,也要注意
__init__
方法的线程安全,确保它也只在实例第一次创建时执行,这通常通过一个内部标志位(如
_initialized
)来控制。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

769

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

661

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

764

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

659

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1325

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

710

2023.08.11

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 11.1万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号