1、定义
__new__:构造方法(负责对象的创建), 通常用于控制生成一个新实例的过程。它是类级别的方法,是一个静态方法。
__init__:初始化方法( 负责对象的初始化),通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法,是一个实例方法。
2、区别
触发时机
__new__:创建一个新实例花对象时触发__new__,生成一个新实例
__init__:实例化对象生成后触发__init__,来进行实例的初始化
当二者同时存在且new返回的是本类实例对象时,new先触发,init再new后面触发;
当二者同时存在且new返回的是其他类实例对象时,new先触发,init不触发;
传参
__new__:必须传参,必须传入cls,其他参数酌情传参
__init__:不必须传参,可以不进行传参
返回值:
__new__:至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供,__new__必须要有返回值,返回实例化出来的实例,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例。
根据传参返回的实例对象,如果返回的是本类实例对象时,才会调用本类的初始化方法(__init__);如果返回的是其他类的实例对象,则不会调用本类的初始化方法(__init__)
__init__:没有返回值
案例集锦:
1、new返回本类对象实例,此时触发本类中的init方法
### 单例模式
# 创建类B
class B():
# 初始化方法
def __init__(self):
self.ccc = 2
self.ddd = 3
def run2(self):
print(8888888888888888888888888888888)
# 创建类A
class A():
# 私有属性
_obj = None
# 构造方法
def __new__(cls, *args, **kwargs):
if cls._obj == None:
cls._obj = super().__new__(cls) # 传参传的cls是本类对象,且最后return返回本类对象实例
return cls._obj
# return object.__new__(B)
# 初始化方法
def __init__(self):
self.a = 2
self.b = 3
def run(self):
print(222222222222222222222222)
# 测试
# 无论实例多少次,id都是指向同一个地址,实现单例模式
aaa = A()
bbb = A()
ccc = A()
ddd = A()
print(id(aaa))
print(id(bbb))
print(id(ccc))
print(id(ddd))
print(type(aaa))
# 调用本类中的方法、属性
print(aaa.a)
print(aaa.b)
print(aaa.run())
### 非单例模式
# 创建类B
class B():
# 初始化方法
def __init__(self):
self.ccc = 2
self.ddd = 3
def run2(self):
print(8888888888888888888888888888888)
# 创建类A
class A():
# 私有属性
_obj = None
# 构造方法
def __new__(cls, *args, **kwargs):
# if cls._obj == None:
# cls._obj = super().__new__(cls) # 传参传的cls是本类对象,且最后return返回本类对象实例
# return cls._obj
# return object.__new__(B)
return super().__new__(cls) # 传参传的cls是本类对象,且最后return返回本类对象实例,非单例模式
# 初始化方法
def __init__(self):
self.a = 2
self.b = 3
def run(self):
print(222222222222222222222222)
# 测试
# 无论实例多少次,id都是指向同一个地址,实现单例模式
aaa = A()
bbb = A()
ccc = A()
ddd = A()
print(id(aaa))
print(id(bbb))
print(id(ccc))
print(id(ddd))
print(type(aaa))
# 调用本类中的方法、属性
print(aaa.a)
print(aaa.b)
print(aaa.run())
2、new返回其他类对象实例,本类中的init方法不触发,可调用B类的属性、方法
# 创建类B
class B():
g = 55
h = 66
def run2(self):
print(8888888888888888888888888888888)
# 创建类A
class A():
# 私有属性
_obj = None
# 构造方法
def __new__(cls, *args, **kwargs):
# if cls._obj == None:
# cls._obj = super().__new__(cls) # 传参传的cls是本类对象,且最后return返回本类对象实例
# return cls._obj
# return super().__new__(cls) # 传参传的cls是本类对象,且最后return返回本类对象实例,非单例模式
return object.__new__(B, *args, **kwargs) # 传参传的其他类对象B,最后return返回B类对象实例,可调用B类的方法、属性
# 初始化方法
def __init__(self):
self.a = 2
self.b = 3
def run(self):
print(222222222222222222222222)
# 测试
# 无论实例多少次,id都是指向同一个地址,实现单例模式
aaa = A()
bbb = A()
ccc = A()
ddd = A()
print(id(aaa))
print(id(bbb))
print(id(ccc))
print(id(ddd))
print(type(aaa))
# 调用B类中的方法、属性
print(bbb.g)
print(bbb.h)
bbb.run2()
注意:如果new()没有返回cls(即当前类)的实例,那么当前类的init()方法是不会被调用 的。如果new()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。