python单例模式及__new__的应用

python__new__

使用 类名() 创建对象时,python首先会调用__new__方法为对象分配空间
如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用 的。

class Foo():
    def __new__(cls, *args, **kwargs):# 不return则不会执行初始化方法
        print("调用__new__方法")
        return super().__new__(cls) # 必须返回对象的引用

    def __init__(self, *args, **kwargs):
        print("调用__init__方法")

foo = Foo()
print(foo)
print (type(foo))

打印结果:

调用__new__方法
调用__init__方法
<__main__.Foo object at 0x00000182A65959B0>
<class '__main__.Foo'>
  • 重写 _new_ 方法 一定要 return super()._new_(cls)
  • 否则 Python 的解释器 得不到分配了空间的 对象引用,就不会调用对象的初始化方法
  • 注意:_new_ 是一个静态方法,在调用时需要 主动传递 cls 参数
  • cls:当前正在实例化的类。 如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类
    的__new__()方法。

例如,如果当前类是直接继承自object,那当前类的__new__()方法返回的对象应该为:

def __new__(cls, *args, **kwargs):
       ...
       return object.__new__(cls)

注意:

  • Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写 _new_(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。
  • 而如果新式类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类*(必定要是
    新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__() 方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死 循环。
  • 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。因此必须避免类似以下的写法:在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)
    使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环.

示例:

class Foo():
    def __new__(cls, *args, **kwargs):
    
        return object.__new__(Stranger)

    def __init__(self, *args, **kwargs):
        pass

class Stranger(object):
    pass


foo = Foo()
print(foo)
print (type(foo))

结果:

<__main__.Stranger object at 0x000001A267706940>
<class '__main__.Stranger'>

python单例模式

# 单例模式
class Single(object):
    __obj = None
    __init_flag = True
    
    # 实现只实例化对象一次
    def __new__(cls, *args, **kwargs):
        
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

    
    
    # 初始化对象
    # def __init__(self):
    #     print("实例化")
    
    # 初始化一次   
    def __init__(self):
        if Single.__init_flag:
            print("实例化")
            Single.__init_flag = False

a = Single()
b = Single()
print(a)
print(b)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值