首页 > 编程语言 >python 单例模式

python 单例模式

时间:2023-07-28 10:14:04浏览次数:42  
标签:__ python self 模式 instance 实例 单例 new cls

python 单例模式

单例模式是一种设计模式,目的是确保一个类只有一个实例,并提供一个全局访问点来获取该实例。

有些类只需要一个全局唯一的实例,例如数据库连接池、线程池、日志记录器等。使用单例模式可以确保这些类只有一个实例存在,从而避免了资源的浪费和不一致的状态。

单例模式通常包含以下几个要素:

  1. 私有化构造方法:将类的构造方法私有化,使得外部无法直接实例化该类。

  2. 静态实例变量:在类中定义一个静态变量,用来保存类的唯一实例。

  3. 全局访问点:提供一个全局的静态方法或属性,用来获取类的唯一实例。通过该访问点,可以在任何需要使用该实例的地方获取到单例对象。

示例代码如下:

class A(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(A, cls).__new__(cls, *args, **kw)
        return cls._instance

这段代码定义了一个名为 Conf 的类,它实现了单例模式,并且在多线程环境下保证线程安全。

解释

__new__函数

__new__ 函数在 Python 中创建并返回一个对象实例,在对象创建之前被调用,用来控制对象的创建过程。

__new__ 方法的定义形式如下:

def __new__(cls, *args, **kwargs):
    # 实现代码
    return object.__new__(cls)

cls 参数代表要创建的类本身,*args**kwargs 是用来传递给类的构造方法的参数。

__new__ 方法的作用是创建并返回一个类的实例。可以在对象实例化之前对对象进行定制化的操作。通常情况下不会直接重写 __new__ 方法,而是在类的构造方法 __init__ 中进行对象的初始化和属性赋值。

__new__ 方法通常用于以下情况:

  1. 当需要控制对象的创建过程,或者需要返回一个不可变的对象时,可以重写__new__方法。
  2. 当需要自定义类的实例化过程,或者需要改变实例化的行为时,可以重写__new__方法。

实现过程

  1. A类中定义了一个类变量 _instance,用来保存类的唯一实例。该变量在类的作用域内是全局唯一的。

  2. 在 __new__ 方法中,首先判断 _instance 是否已经存在实例。如果不存在,则通过调用 super(A, cls).__new__(cls, *args, **kw) 创建一个新的实例,并将其赋值给 _instance。这样第一次调用 __new__ 方法时会创建一个新的实例,并将其赋给 _instance。从第二次开始的调用,由于 _instance 已经存在实例,就直接返回该实例。

  3. 无论是创建了新的实例还是直接返回已存在的实例,都会将实例返回。无论多少次调用该类的构造方法,都只会返回同一个实例,实现了单例模式。因为 _instance 是一个类变量,所以它在类的所有实例之间是共享的,保证了只有一个实例被创建和返回。

  4. 这段代码还加入了线程安全的考虑。因为在多线程环境下,可能会有多个线程同时调用该类的构造方法。为了保证线程安全,通过检查 cls._instance 是否已经存在实例,可以避免多个线程同时创建实例的情况,从而保证了线程安全性。

扩展

上面的 cls 可以换成 self 吗

在 __new__ 方法中,cls 是一个约定俗成的参数名,代表当前类本身。虽然可以将 cls 替换为 self,但这是不推荐的做法,因为 self 通常用于表示实例对象,而不是类对象。

在 __new__ 方法中,cls 参数的作用是指明要创建的类。当调用一个类的构造方法时,会自动将类作为第一个参数传递给构造方法,通常我们将该参数命名为 self

而在 __new__ 方法中,由于还没有实例化对象,所以无法使用 self 来表示对象实例。因此使用 cls 来代表要创建的类本身。

cls 和 self 的区别

  • cls:cls 是一个约定俗成的参数名,表示类本身。它在类方法(class method)中使用,用于引用类的属性或调用类的方法。cls 通常作为第一个参数传递给类方法,以区分它与实例方法的不同。通过 cls,我们可以在类方法中访问类的静态成员或创建新的类实例。
class MyClass:
    @classmethod
    def class_method(cls):
        print("This is a class method")

MyClass.class_method()  # 调用类方法
  • self: self 也是一个约定俗成的参数名,表示类的实例本身。它在实例方法(instance method)中使用,用于引用实例的属性或调用实例的方法。self 作为第一个参数传递给实例方法,以便在方法内部访问实例的成员。
class MyClass:
    def __init__(self, name):
        self.name = name

    def instance_method(self):
        print("My name is", self.name)

obj = MyClass("John")
obj.instance_method()  # 调用实例方法

使用场景举例

cls 在类方法中使用,用于引用类的属性或调用类的方法。它通常用于在类方法内部访问类级别的属性或创建新的类实例。

class MyClass:
    class_attribute = "Class Attribute"

    @classmethod
    def class_method(cls):
        print(cls.class_attribute)  # 访问类级别的属性

MyClass.class_method()  # 调用类方法
print(MyClass.class_attribute)  # 直接访问类级别的属性

self在实例方法中使用,用于引用实例的属性或调用实例的方法。它通常用于在实例方法内部访问实例级别的属性或调用其他实例方法。

class MyClass:
    def __init__(self):
        self.instance_attribute = "Instance Attribute"

    def instance_method(self):
        print(self.instance_attribute)  # 访问实例级别的属性

obj = MyClass()
obj.instance_method()  # 调用实例方法
print(obj.instance_attribute)  # 访问实例级别的属性

标签:__,python,self,模式,instance,实例,单例,new,cls
From: https://www.cnblogs.com/ConfusedChenSir/p/17586811.html

相关文章

  • 【Python】异常
     异常defexecpt_test(a,b):result=a/breturnresultdefdivide_numbers(a,b):try:execpt_test(a,b)exceptZeroDivisionError:print("除数不能为零!")print(divide_numbers(10,0)) ......
  • Android-单例模式
    单例模式意图:这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 publicclassSingleton{privatestaticSingletoninstance=newSingleton();......
  • python教程 入门学习笔记 第2天 第一个python程序 代码规范 用默认的IDLE (Python GUI
    四、第一个python程序1、用默认的IDLE(PythonGUI)编辑器编写2、在新建文件中写代码,在初始窗口中编译运行3、写完后保存为以.py扩展名的文件4、按F5键执行,在初始窗口观看运行结果5、代码规范:1)先保存再执行2)一句代码单独占一行3)语法中的符号,必须使用英文4)代码前面不能有......
  • 掌握 Python RegEx:深入探讨模式匹配
    动动发财的小手,点个赞吧!什么是正则表达式?正则表达式通常缩写为regex,是处理文本的有效工具。本质上,它们由一系列建立搜索模式的字符组成。该模式可用于广泛的字符串操作,包括匹配模式、替换文本和分割字符串。历史数学家StephenColeKleene在20世纪50年代首次引入正则......
  • 八、Web应用模式
    8.1、web应用模式在开发Web应用中,有两种应用模式:前后端不分离[客户端看到的内容和所有界面效果都是由服务端提供出来的。前后端分离【把前端的界面效果(html,css,js分离到另一个服务端,python服务端只需要返回数据即可)】前端形成一个独立的网站,服务端构成一个独立的网......
  • python截取文本
    defsclip():withopen("file.txt","r")asfile:lines=file.readlines()first_line=lines[0:2]last_10_lines=lines[5:]first_line.extend(last_10_lines)withopen("output.txt","w")......
  • Python生成30万条Excel 测试数据
    使用Python生成30万条Excel测试数据fromopenpyxlimportWorkbookfromconcurrent.futuresimportThreadPoolExecutor#定义生成数据的函数defgenerate_data(start,end,sheet):#生成数据foriinrange(start,end+1):sheet.append([i,f"姓名{i......
  • Keepalived非抢占模式配置
    Keepalived非抢占模式配置1、前言非抢占模式,这种模式主要是针对主机崩溃,集群已经重新选出新的主机,并且原来的主机重新上线后并不争夺主机的情况。这种模式适合那些倾向于认为崩溃的主机即便上线还是会出现崩溃的场景。这种模式的核心思想是将所有节点的优先级(priority)值设为相......
  • python虚拟环境拷贝到另一台电脑
    背景介绍:建立了虚拟环境后,在其中安装的包很多,也很费时间,你想将这个MyApp放到其他电脑上去开发,是不是直接复制MyApp文件夹就可以了呢?不行!因为在建立虚拟环境时,虚拟环境中的python.exe,pip.exe......等一些文件会“硬编码”,记录的是绝对路径,放到其他电脑后,因为路径不同会出错!......
  • Python基础day54 Django2
    配置文件的介绍#注册应用的INSTALLED_APPS=['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.......