python3 __init__() 和 __new__()方法,实例创建过程,以及单例模式创建

python中实例创建过程离不开两个函数__init__()  和 __new__(),__new__()负责创建instance(实例),而__init__()负责customize(个性化定制,或者称为初始化 -- 其他语言中称呼),然后返回给caller(调用者),即完成实例创建。有一个比喻特别适合这两个角色的工作: 我们生活中房子建造过程就如同python中实例创建,楼看作类,具体到某个楼就是实例。

 

  • 第一步:楼房从无到未装修的楼房 --- 这一步在实例化中由__new__(cls)方法完成,__new__(cls)创建新的内存空间
  • 第二步:装修为成品 ---- __new__(cls)出来的相当于一个空的房子,在计算机中实际工作开辟出一个新的内存__new__(cls), 然后调用__init__() 方法把实例变量(__init__()函数中变量)copy(深拷贝,放置可变对象共享内存地址)一份到这个空间,即完成实例化过程

下面讲讲这两个函数:

1.  __new__(cls):  

new方法是一个静态方法,无论加不加@staticmethod装饰器他都是静态方法

  new函数是在创建实例时被调用,功能:创建实例,创建实例时调用的是父类或者超类的__new__(cls)方法,其中自动传入创建实例的类,返回一个实例对象,然后调用__init__()方法来customize,如果__new__(cls)返回的不是一个cls的实例则不会调用__init__()方法,由于这种设计就产生一种单例模式实现方式(通过重写__new__()方法实现

注意: 如果自己重写了new方法,且调用了自己的__new__(cls)方法将会导致无限递归,死循环

例如(死循环例子):

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

正确写法:

class Test:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)  # 加入参数是放置父类中new需要参数情况,不加*args, **kwargs也不没问题
# 借此我们就可以通过重写__new__()方法来实现单例模式借此我们就可以通过重写__new__()方法来实现单例模式
 
class Test:
    __obj = None
    def __new__(cls, *args, **kwargs):
        if cls.__obj is None:
            cls.__obj = super().__new__(cls)  # 利用父类创建实例
        return cls.__obj

2.   __init__(self, *args, **kwargs):

    __new__方法下存放是实例变量, 作用初始化实例变量。

    new方法创建实例后由__new__()方法来customize(new方法把它接收到的*args, **kwargs参数传递个__init__方法

3.  单例模式案例补充:

(1) 通过静态方法或者类方法实现
class Test:
    __obj = None

    @staticmethod
    def get_instance(*args, **kwargs):  实例化时需要加的参数
        if Test.__obj is None:
            Test.__obj = Test(*args, **kwargs)
        return Test.__obj
(2) 通过装饰器实现
def singleton(cls):  # cls为类
    dic = dict()
    def inner(*args, **kwargs): # 这里加参数是因为有可能类创建时传入参数了,所以这里需要加(根据装饰器原理,真正调用的是inner方法,然后inner返回实例)
        if cls not in dic:
            dic[cls] = cls(*args, **kwargs)
        return dic[cls]
    return inner
 
@singleton  # 加上装饰器即可实现
class T:
    pass
(3). 通过类方法方法实现
class TestOne:
    __obj = None
    @classmethod
    def get_instance(cls, *args, **kwargs):
        if cls.__obj is None:
            cls.__obj = cls(*args, **kwargs)
        print(cls)
        return cls.__obj


tt = TestOne.get_instance()
tt1 = TestOne.get_instance()
print(id(tt), id(tt1)) # 判断是否为同一个实例

 

我就讲这些了,如果有什么问题或者心得可以一块讨论学习,也请大家批评指正

 

你可能感兴趣的:(python,单例模式)