python实现单例模式总结

本文探讨了Python中实现单例模式的三种方法:装饰器、元类和继承。特别指出,常见使用`cls._instance = super().__new__(cls, *args, **kwargs)`的方式在对象创建时存在错误,因object的`__new__`方法不需要参数。虽然这三种方法本质上都是在创建实例时检查是否已有实例,但继承方式通过改造`new`方法来实现,并且在已有实例时,属性会得到更新。" 108735188,9162229,Python Selenium滑块验证码解决方案:OpenCV识别与自动化操作,"['Python爬虫', '验证码破解', '图像识别', 'Selenium库', 'OpenCV库']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 装饰器
def singleton(cls):
    def get_instance(*args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = cls(*args, **kwargs)
        return cls._instance
    return get_instance
  • 元类
class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "__instance"):
            cls.__instance = super().__call__(*args, **kwargs)
        return cls.__instance
  • 继承

 这个地方,我看了好多博客,都是cls._instance = super().__new__(cls, *args, **kwargs)

但是呢, 这是错误的!!!

因为Singleton的超类是object,而object调用__new__方法的时候是不需要任何参数的。

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            # 注意,这个地方通过超类来获取实例的时候,传递的参数是超类需要的
            # 超类不需要的是不能传递的
            # 而这个地方Singleton的超类是object,因此是不需要任何参数,除了cls的
            cls._instance = super().__new__(cls)
        return cls._instance

点评:这三个方法实现代理模式,本质上是一致的。都是在创建新的实例的时候,会对该类是否已经创建了实例做判断。如果没有实例,则产生新的实例;如果已经有,则略过,返回旧的实例。

但是呢,通过继承实现的单例模式是有点突出的。因为它跟其他方式有点不同,它是通过new方法的改造实现的。如果之前有就返回之前的实例;如果没有,就创建新的实例。

需要知道的是,创建实例,有两个过程,一个是new方法创建实例对象,然后再由init方法初始化实例对象。

也就是继承那种方式,new返回的实例,会再通过init方法初始化。

也就是,其属性会得到更新。

例子如下:

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super().__new__(cls)
        return cls._instance

class A(Singleton):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return "a is " + str(self.a) + "; b is " + str(self.b)
a1 = A(1, 2)
print(a1)
a2 = A(2, 3)
print(a2)
print("a1 is a2 => ", a1 is a2)

结果是这样的

a is 1; b is 2
a is 2; b is 3
a1 is a2 =>  True

可以看见,实例的属性是得到更新的。。。。。

而其他两种方式中,都是在new方法之前对该类是否已有实例进行判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值