Python笔记:单例实现方法

【Python】深入理解Python中的单例模式:用元类、装饰器和模块实现高效的单例设计 单例模式是一种重要的设计模式,旨在确保一个类的实例在整个应用程序中仅存在一个。Python作为一种动态语言,为实现单例模式提供了多种方式,包括模块级单例、装饰器和元类等方法。本文将深入探讨这些实现方式,逐步解析它们的工作原理和适用场景。通过提供丰富的代码示例和详细的中文注释,我们将展示如何在Python中灵活使用单例模式,以满足不同场景下的资源管理需求。 阅读详情

0. 引言

在python代码的写作中,我们有时需要全局化某一对象,即让这一对象有且只有一个,从而实现共同控制,共享存储空间等功能。

当然,一种简单粗暴的方法就是直接定义变量之后然后将其实例化然后再设置为全局变量,但是这种操作非常野蛮,且必须确保其执行顺序处于最前方。

另一种简单粗暴的方法是如果确定这一变量必然为某个类的操作对象时,我们可以将其定义为该类的类变量,利用类变量先天的唯一性实现全局的操作。

但是,同样的,这样的方式也不够优雅,更多的情况下,我们希望的是对该类的现状透明化操作,反正就是要用了我就实例化一下,但是实例化之后返回的永远是同一个类的实例,即单例的方法。

单例实现的根本思路事实上就是对类的实例化过程进行重载,当发现类已经被实例化过之后,就返回已经实例化得到的类的实例,否则就进行实例化然后返回实例化对象。

因此,要对单例的实现有一个更为系统的了解,我们首先来考察一下python类的实例化过程。

1. python类的实例化过程

我们首先来看一下python类从定义到实例化的完整过程:

  1. 类变量的实例化以及类方法的申明;
  2. 元类的__new__
  3. 元类的__init__
  4. 元类的__call__
  5. 类本身的__new__
  6. 类本身的__init__

其中,前三步发生于类的申明过程中,后三步在每一次类的实例化过程中都会执行一次。

具体的,我们可以考察如下代码例子:

class MyMetaclass(type):
    print("MyMetaclass")
    
    def __new__(cls, name, bases, attrs):
        print("MyMetaclass :: __new__")
        return super().__new__(cls, name, bases, attrs)
    
    def __init__(self, *args, **kwargs):
        print("MyMetaclass :: __init__")
        return super().__init__(*args, **kwargs)
    
    def __call__(self, *args, **kwargs):
        print("MyMetaclass :: __call__")
        return super().__call__(*args, **kwargs)
    
class MyClass(list, metaclass=MyMetaclass):
    print("MyClass")
    
    def __new__(cls, *args, **kwargs):
        print("MyClass :: __new__")
        return super().__new__(cls)

    def __init__(self, *args, **kwargs):
        print("MyClass :: __init__")
        return super().__init__(*args, **kwargs)

定义完成后上述代码即会打印出如下结果:

MyMetaclass
MyClass
MyMetaclass :: __new__
MyMetaclass :: __init__

之后,我们对MyClass类进行实例化,会打印出结果如下:

MyMetaclass :: __call__
MyClass :: __new__
MyClass :: __init__

不过坦率地说,对于类的申明过程以及实例化过程的更加深入的理解,还有元类这个概念存在的本身事实上我就不太了解了,毕竟不是科班出身,虽然写了不少python代码,但是对于python本身的理解还是不够的。

下面就是一些我目前不太理解的问题:

  1. python在类的申明过程中是通过什么机制进行类变量的实例化和类方法的申明的,这个过程叫做什么?
  2. 元类的定义是什么?为什么要有元类的存在,它能够实现什么特别的方法?

如果有朋友对这部分内容有足够的了解。欢迎进行补充讲解。

2. 单例的实现方法

如前所述,单例的实现方式事实上就是对类的实例化过程进行介入,重载其中某些过程,使得当类的实例以及存在时,直接返回已经实例化的类的实例,从而确保这一个类的实例对象永远为同一个。

而根据介入时间点的不同,单例的实现方式大致可以分为以下三种,由前至后分别为:

  1. 通过装饰器方式重载类的实例化方法
  2. 重载元类的__call__方法
  3. 重载类的__new__方法

1. 通过装饰器的方式实现

通过装饰器的方式进行单例的实现事实上就是完全重载类的实例化方法。

给出其代码实现如下:

def singleton(cls):
    instances = {}
    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance

@singleton
class Counter(object):
    def __init__(self, counter=0):
        self.counter = counter

这种实现方式直接重载了Counter()函数,当这个类已经被实例化过之后,后续在进行Counter()函数的调用,装饰器会直接调用getinstance()方法,返回现有的类的实例,此时后续从元类的__call__方法到类本身的__new__与__init__方法都不会再执行。

给出例子如下:

a = Counter()
print(a.counter) # 0
b = Counter(2)
print(b.counter) # 0
b.counter += 1
print(b.counter) # 1
print(a.counter) # 1

2. 通过重载元类的__call__函数的方式实现

重载元类的__call__函数是另一种实现单例的方式。

我们同样给出代码样例如下:

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]
    
class Counter(object, metaclass=Singleton):
    def __init__(self, counter=0):
        self.counter = counter

由于类本身的__new__()方法与__init__()方法都是在元类的__call__()函数中进行实现的。因此,上述重载方式在二次实例化过程中也不会再执行类的__new__()方法与__init__()方法。

a = Counter()
print(a.counter) # 0
b = Counter(2)
print(b.counter) # 0
b.counter += 1
print(b.counter) # 1
print(a.counter) # 1

3. 通过重载类的__new__函数的方式实现

单例的第三类实现方式是通过重载类的__new__()方法进行实现。

给出代码样例如下:

class Counter(object):
    _instances = {}
    def __new__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__new__(cls, *args, **kwargs)
        return cls._instances[cls]
        
    def __init__(self, counter=0):
        self.counter = counter

可以看到,其代码实现方式与上述重载metaclass的__call__()函数方式几乎一模一样,但是其区别在于,重载__new__()函数的情况下类在实例化过程中依然会走完完整地实例化流程。因此,后续他依然会去执行__init__()函数操作,可能会带来使用上的隐患,需要注意。

给出一个例子如下:

a = Counter()
print(a.counter) # 0
b = Counter(2)
print(b.counter) # 2
b.counter += 1
print(b.counter) # 3
print(a.counter) # 3

4. 总结

综上,单例的实现本质上来说就是通过某种方式介入到类的实例化过程当中。当发现类已经进行了实例化之后,就直接返回现有类的实例。

根据介入时间点的不同,单例的实现方式大致可以分为以下三种,由前至后分别为:

  1. 通过装饰器方式重载类的实例化方法
  2. 重载元类的__call__方法
  3. 重载类的__new__方法

给出各个模式下的单例在二次实例化过程中会进行的操作如下:

methodmetaclass.__call__class.__new__class.__init__
装饰器XXX
重载元类的__call__方法OXX
重载__new__方法OOO

3. 参考链接

  1. https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
  2. https://www.liaoxuefeng.com/wiki/1016959663602400/1017592449371072
2020计算机专业保研夏令营面经:中科院计算所网数机试题目 计算所网络数据科学与技术重点实验室的第一阶段是机试。机试不限程序语言,要求提交源代码。 阅读详情

相关推荐

别再让CPU干GPU的活了:CST Studio Suite GPU加速深度调优指南(从驱动版本到任务管理器监控)

本文深入探讨了CST Studio Suite的GPU加速深度调优方法,从NVIDIA驱动版本选择到系统级资源管理,再到实时监控与瓶颈诊断技术。通过科学的驱动优化、GPU资源管理策略和高级调优技巧,显著提升仿真效率,特别适合电磁仿真工程师和硬件加速需求的专业用户。

weixin_28740299的博客 166

python之metaclass+singleton(三)

Singletonsingleton(单例模式)《设计模式之禅》一书中给出解释: Ensure a class has only one instance, and provide a global point of access to it. 意为:保证一个类只有一个实例,并且向整个系统提供这个实例。 这种模式的应用场景是什么呢?最简单的就是打印机,一个时刻,打印机只可能打印一个文件,只有能

wushirenfei的博客 1695

永磁同步电机矢量控制——电流内环前馈解耦策略

在采用永磁同步电机矢量控制时,ud和uq的指令值存在耦合项。需要对其进行解耦,目前,常用的解耦设计方法有前馈解耦、偏差解耦以及内模控制,本文主要分享电流内环前馈解耦控制策略。

a12312341ll的博客 8693

python cls.instance_Python中的单例模式

单例模式单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 App...

weixin_33617670的博客 668

4、I3C协议详解

I3C最初的设计目的是为移动设备创建一个能够使用多个传感器的单一接口。随着现代化移动设备对于传感器数量的增加以及对性能的提高,I2C和SPI已经达到了他们所能支持的临界点,而I3C的出现就是为了解决这一问题,I3C可以在同一根主线上支持更多的传感器设备,而且不会因为要支持中断或睡眠模式而增加额外的逻辑信号。I3C可以在更低功耗的情况下提供更快的传输速率,该特性的提升不止是对移动设备,对其他的嵌入式设备也都是很大的帮助。例如穿戴设备,需要在有限的物理空间中使用多个传感器并且要求更小的耗电。 一、简述..

迟子涵925的博客 2万+

Deepseek接入QQ机器人:实现拟人化概率回复的完整指南

大语言模型API正在快速改变即时通讯工具的交互方式。通过标准化的OpenAI兼容接口,开发者可以将Deepseek等AI服务嵌入到QQ机器人等IM场景中,实现自然语言对话能力。其核心原理在于事件驱动架构:消息接收层通过OneBot协议获取群聊内容,业务层利用概率过滤与冷却机制控制回复节奏,再由大模型生成拟人化文本。这种设计不仅避免了机器人刷屏,还能通过系统提示词塑造性格,营造真实的社群陪伴体验。适用于粉丝群互动、内容订阅、小规模客服等场景,同时支持多群独立配置、关键词加权回复及上下文记忆扩展。在实际工程中,

weixin_29051245的博客 460

Python 中的单例模式

单例模式 单例模式(SingletonPattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。 比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 Ap...

weixin_34252686的博客 293

uniapp(全端兼容) - 最新详细实现pdf在线预览功能,uniapp内置预览PDF文件功能,uniapp在安卓app|苹果app|h5网页网站|微信小程序中打开pdf进行在线预览(详细示例源码)

uni-app,安卓Android,苹果ios,App端,H5网页,移动端网站,微信小程序,支付宝小程序,nvue,vue,pdf文档,pdf文件,office,uniapp 预览pdf,uniapp怎么做pdf预览,uniapp如何实现全平台兼容的pdf在线预览,uniapp怎么在h5打开pdf文档,实现PDF在线预览,H5移动端文件预览pdf,文件下载和预览,uniapp App端pdf文件预览,app移动端在线预览pdf文件,无法预览pdf怎么办,有没有预览pdf的插件,根本打不开咋办,uniapp使

✅ 精选推荐文章 1万+

Python单例模式(Singleton)的多种实现

转载自:https://zhuanlan.zhihu.com/p/37534850 有删改 很多初学者喜欢用全局变量,因为这比函数的参数传来传去更容易让人理解。确实在很多场景下用全局变量很方便。不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱。你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某个地方被做了怎样的操作。 因此对于这种情况,有种更好的实现方式: 单例(Singleton) 单例是一种设计模式,应用该模式的类只会生成一个实例。 单例模式保证了在

weixin_43407319的博客 590

Altium Designer(AD24/25)如何在PCB设计阶段做阻抗匹配

目前阻抗匹配多直接有制版厂进行,PCB设计师在设计阶段可不关注阻抗设计,在加工阶段只需标注需要控制的阻抗线,制板厂即可按照要求对阻抗线进行调整和控制。但是对于设计师来讲掌握阻抗线的设计方法也是非常必要的。本文介绍Altium Designer(AD24/25)如何在PCB设计阶段做阻抗匹配。

fydar的博客 893

SAP BTP ABAP RAP 开发对象命名规范与落地实践

摘要:SAP BTP ABAP开发中的命名规范实践 在企业级ABAP开发中,命名规范是提升交付效率的工程化手段。SAP推荐采用[/<namespace>/][<prefix>]_<object_name>_[<suffix>]的结构化命名框架,解决多对象、多团队的协同问题。关键实践包括:使用组织专属命名空间避免冲突;通过prefix区分同类型对象的不同语义(如UI_/API_);object_name体现业务语义而非技术细节;suffix表达次级差异。在具体对

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1435

基于爬虫刷新某网站访问量!我说怎么上千万呢!

前言:前一段时间看到有博友写了爬虫去刷新博客访问量一篇文章,当时还觉得蛮有意思的,就保存了一下,但是当我昨天准备复现的时候居然发现文章404了。 所以本篇文章仅供学习交流,严禁用于商业用途 当我在写文章的同时,代码依然在运行,亲测是有效滴。 你很容易会发现你写的那些水文章的url都有一个共同特点,前面都是固定的,就是后面一串数字不一样,这串数字是利用某种算法生成,因为我不会,这里我不展开讲了。我只需要把后面的数字拿过来就好了。 https://blog.youkuaiyun.com/SuperBette.

爬遍所有网站 830

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Python 实现单例

Python 实现单例 文章目录Python 实现单例起步__new__函数元类 metaclass装饰器函数装饰器类装饰器方法静态方法 staticmethod类方法 classsmethod名字覆盖属性共享 起步 单例模式是一种常用的软件设计模式,用来确保一个类只会有一个实例存在。 以下是 Python 中实现单例模式的多种方法,环境基于 Python3.6.6。 __new__函数 cl...

有关心情 8277

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

python 单例,Python实现单例的四种方法

一、通过模块调用的方式实现在python3中,首次导入模块文件时,会在程序目录下的__pycache__目录下生成pyc文件,再次导入时,将直接加载pyc文件。因此,只需要把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。二、使用__new__方法(饿汉式)# 饿汉式class HungrySingleton(object):def __new__(cls, *args, **kwar...

weixin_28995139的博客 361

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

python单例实现方法

转载 https://www.cnblogs.com/huchong/p/8244279.html 1.使用模块 其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做: mysingleton.py class Singleton(object): def foo(self): p

weixin_43366097的博客 181

Python 用__new__方法实现单例

Python重载__new__方法实现单例

hiudawn 3002

单例python_Python 用__new__方法实现单例的操作

介绍init 方法通常用在初始化一个类实例时候,但其实它不是实例化一个类的时候第一个被调用 的方法。当使用 Student(id, name) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 new 方法。new方法接受的参数虽然也是和init一样,但init是在类实例创建之后调用,而 new方法正是创建这个类实例的方法。new为对象分配空间,是内置的静态方法,new在内存中为对象分配了空...

weixin_39691748的博客 285

今日讲解之python-实现单例模型的四种方法

这是看了林海峰老师讲解单例模型的实现方法的总结来与大家分享~ 一、@classmethod ->通过类方法实现 '''class Foo: # 定义一个类的数据属性,用于接收对象的实例,判断对象是否只有一个 _instance = None def __init__(self, name, age): self.name = name self.age = age @classmethod def singlenton(

m0_51734025的博客 921

单例模式:Python中实现单例的几种方式

单例模式的核心要点:1. 一个类只能创建一个实例。2. 该实例必须由类自身负责创建。3. 必须向整个系统提供这个实例。在 Python 中,由于对象的创建和初始化过程相对透明,实现单例需要一些技巧。下面我们逐一探讨。方法优点缺点模块级单例最简单,天然线程安全无法控制实例化时机,无延迟加载类装饰器语法简洁,可传参类型检查破坏,多线程需加锁元类面向对象,控制力强复杂度高,需理解元类__new__ 重写最直观,Pythonic__init__ 重复执行,需额外处理。

m0_51069462的博客 481

Python 使用__new__方法实现单例

python __new__方法实现单例模式,以及如何实现的带锁的更安全的单例,最后介绍单例的应用场景。

yuxuan89814的专栏 1037

单例python_小结python单例的两种实现方法

python单例的两种实现方法介绍(附代码)本篇文章给大家带来的内容是关于python单例的两种实现方法介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。这两天在看自己之前写的代码,所以正好把用过的东西整理一下,单例模式,在日常的代码工作中也是经常被用到,所以这里把之前用过的不同方式实现的单例方式整理一下装饰器的方式这种方式也是工作中经常用的一种,用起来也比较方便,代码...

weixin_39924674的博客 73

python中的单例与实例

单例(Singleton):就像一个特别的玩具,整个程序中只有一个,None就是这样的单例。实例(Instance):就像从工厂里生产出来的玩具,每个都有自己的特点,从类里创建出来的对象就是实例。检查None:因为None是单例,用is来检查变量是不是None是最直接的方式。

2302_80012625的博客 421

python 进程单例,起停功能

python文件锁实现进程单例 通过参数控制进程起停, 类似 httpd -k #!/usr/bin/python import os import getopt import fcntl import time import sys def main(): while(True): print os.getpid() time.sleep(3)

CC 2396

Python 之 单例

单例 目标 单例设计模式 new 方法 Python 中的单例 单例设计模式 设计模式 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性 单例设计模式 目的 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例 每一次执行 类名() 返回的对象,内存地址是相同...

qq_43688472的博客 212

以单例来讲如何用python来new一个对象

python和C语言不同,在构造函数时不能够分配内存空间,但是在构造函数时,也可以通过__new__函数来实现一些跟内存相关的操作,比如单例模式。 估计有很多小盆友不知道什么是单例,python的单例就是在实例化时,不管实例化多少次都用的同一块内存空间。 另外需要说明的是,构造函数需要用__new__来实现,而__init__为初始化函数,__init__在实例化时调用,__new__在构造函数时...

Q.1的博客 2146

python单例装饰器_python:单例装饰器

singleton 的三种写法## instance_map = {}### def get_instance(cls, *args, **kwargs):# if cls not in instance_map:# instance_map[cls] = cls(*args, **kwargs)# # log# instance = instance_ma...

weixin_29669899的博客 336
上一篇: LeetCode笔记:Weekly Contest 202 比赛记录
下一篇: LeetCode笔记:Biweekly Contest 33 比赛记录
Espresso Macchiato
博客等级 码龄7年 2453粉丝 818原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值