先看一个简单的类,包括一个__init__和一个__new__方法
#!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2019-08-22 18:24 # Auth : lihui # File : start.py class A: def __init__(self): print("A __init__") def __new__(cls, *args, **kwargs): print("A __new__") return super(A, cls).__new__(cls) if __name__ == "__main__": A()
先看下执行结果
A __new__ A __init__
从这里可以看出,整个对象的初始化过程,是先执行__new__方法,再来执行__init__方法的
看一下Python的官方文档,这里版本是Python3.7.4
从官方文档可以总结出以下几点:
1:创建cls类实例的是__new__方法,如果要得到当前类的实例,得在当前类的__new__方法中调用其父类的__new__方法
2:__new__创建实例之后,返回一个cls实例,传给__init__的self参数,来完成一些初始化工作
3:如果__new__并没有返回一个cls实例,那么__init__方法是不会执行的
4:__init__必须返回None
下面就逐一测试一下
首先可以在__new__和__init__加一些类和实例的打印
#!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2019-08-22 18:24 # Auth : lihui # File : start.py class A: def __init__(self): print("__init__ A") print("__init__", self) def __new__(cls, *args, **kwargs): print("__new__ A") print("__new__", cls) a = super(A, cls).__new__(cls) print("__new__", a) return a if __name__ == "__main__": A()
输出结果如下
__new__ A __new__ <class '__main__.A'> __new__ <__main__.A object at 0x101f0c290> __init__ A __init__ <__main__.A object at 0x101f0c290>
从结果可以看出来__new__里返回的对象a和__init__里初始化的self是同一个class A类型的对象
但如果__new__方法没有返回实例的话
#!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2019-08-22 18:24 # Auth : lihui # File : start.py class A: def __init__(self): print("__init__ A") print("__init__", self) def __new__(cls, *args, **kwargs): print("__new__ A") print("__new__", cls) a = super(A, cls).__new__(cls) print("__new__", a) if __name__ == "__main__": A()
输出结果只有__new__方法的执行情况,__init__并没有执行
__new__ A __new__ <class '__main__.A'> __new__ <__main__.A object at 0x10df32290>
也就是说,这时候class A类型实例都没有创建出来,调用__init__也没啥意义
再如果__new__正常返回了,但是__init__完成之后有一个返回值,看看结果
#!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2019-08-22 18:24 # Auth : lihui # File : start.py class A: def __init__(self): print("__init__ A") print("__init__", self) return True def __new__(cls, *args, **kwargs): print("__new__ A") print("__new__", cls) a = super(A, cls).__new__(cls) print("__new__", a) return a if __name__ == "__main__": A()
这时候就会出现报错
Traceback (most recent call last): File "/Users/lihui/Documents/Python/leetcode/start.py", line 22, in A() TypeError: __init__() should return None, not 'int' __new__ A __new__ <class '__main__.A'> __new__ <__main__.A object at 0x10cc632d0> __init__ A __init__ <__main__.A object at 0x10cc632d0> Process finished with exit code 1
最后再来看下初始化参数传入
#!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2019-08-22 18:24 # Auth : lihui # File : start.py class A: def __init__(self, a, b): print("__init__:", a, b) print("__init__:", id(a), id(b)) self.a = a self.b = b print("__init__:", self.a, self.b) def __new__(cls, *args, **kwargs): print("__new__:", args) print("__new__:", id(args[0]), id(args[1])) return super(A, cls).__new__(cls) if __name__ == "__main__": A(1, 2)
执行结果如下
__new__: (1, 2) __new__: 4347465488 4347465520 __init__: 1 2 __init__: 4347465488 4347465520 __init__: 1 2
在执行A(1, 2)时,先执行类A的__new__方法,cls就是A,args就是1和2,方法里执行A的父类的__new__方法,并入args两个参数,创建了A的实例并返回,实例创建之后就会调用__init__方法,self指向这个实例对象,接收参数进行对象的一些初始化工作,这就是两者的区别