一、new方法
总结,__init__方法中初始化的参数实际上是__new__方法传进去的,所以new方法中必须要接收初始化的参数,用*args,**kwargs来实现
In [166]: class D():
...: def __new__(cls,*args,**kwargs): # 创建对象时参数先传给new,
new指向成功后将参数传给init方法,所以此处如果不写*args,**kwargs
则下面用D(10,20,30,o=100,p=50)创建实例对象时会报new方法只要一个参数
but 6 given!
...: return object.__new__(D)
...:
...: def __init__(self,x,y,z,o=0,p=9):
...: self.x = x
...: self.y = y
...: self.z = z
...: self.o = o
...: self.p = p
...: def dd(self):
...: print("D dd method is running")
...:
In [167]: dit = {"o":100,"p":50}
In [168]: d = D(10,20,30,dit) # 相当于10 20 30 dit四个参数传到*args元组里面去了
In [169]: d.p # 所以p用的是默认值,init前面四个参数用的是元组拆包传值
Out[169]: 9
In [170]: d.o # 所以o传的是个字典dit
Out[170]: {'o': 100, 'p': 50}
In [171]: d = D(10,20,30,*dit) # *表示拆包,1颗*拆的是键
In [172]: d.p
Out[172]: 'p'
In [173]: d.o
Out[173]: 'o'
In [174]: d = D(10,20,30,**dit) # 两颗*表示拆键值对,
即把dit字典拆成o=100,p=50
In [175]: d.p
Out[175]: 50
In [176]: d.o
Out[176]: 100
In [177]: d1 = D(10,20,30,**dit)
In [178]: d2 = D(10,20,30,**dit)
In [179]: id(d1)
Out[179]: 140290162490952
In [180]: id(d2)
Out[180]: 140290162542016
二、单例模式
class D():
...: __instance = None # 不对外访问,_ _私有化
...: __is_init = False
...: def __new__(cls,*args,**kwargs): # 要加*args,**kwargs传参
...: if cls.__instance is None: # 类属性要加cls.访问
...: cls.__instance = object.__new__(D) # 实际创建对象时new只需要一个参数,这里要注意下
...: return cls.__instance
...: def __init__(self,x,y,z,o=0,p=9):
...: if not self.__is_init: # 类属性用类名.或者self.访问,这里找不到cls变量不能用cls.访问
...: self.x = x
...: self.y = y
...: self.z = z
...: self.o = o
...: self.p = p
...: self.__is_init = True
...:
...: def dd(self):
...: print("D dd method is running")
执行结果:
In [186]: d4 = D(10,20,30,o=90,p=80)
In [187]: d5 = D(40,50,60,o=100,p=800)
In [192]: d4.x
Out[192]: 10
In [193]: d4.o
Out[193]: 90
In [194]: d5.o
Out[194]: 90