__new__
考虑以下代码的输出结果:
class A:
print("AAAAA")
def __init__(self):
print("a init")
...
def __new__(cls, *args, **kwargs):
print("a new")
return super(A, cls).__new__(cls)
a = A()
结果为:

__new__
是object的一个静态方法,用于创建对象实例,__init__
用于初始化对象。而上面的 “AAAAA” 则是在加载类的过程中就执行了
多继承下的实例化过程
考虑以下代码输出:
class A:
print("AAAAA")
a_attr = "a"
def __init__(self):
print("a init")
super(A, self).__init__() # 这里的super指的是谁?
...
def __new__(cls, *args, **kwargs):
print("a new")
return super(A, cls).__new__(cls)
class B:
print("BBBBB")
def __init__(self):
print("b init")
super(B, self).__init__() # 这里的super指的是谁?
...
def __new__(cls, *args, **kwargs):
print("b new")
return super(B, cls).__new__(cls)
def bm(self):
print("bbb")
class C(A, B):
print('CCCCC')
def __init__(self):
print('c init')
super(C, self).__init__() # 这里的super指的是谁?
def __new__(cls, *args, **kwargs):
print("c new")
return super(C, cls).__new__(cls)
...
c = C()
print(C.mro())

上述代码中,A和B相互独立,C继承A、B,实例化C(没有调用super的实例化),可以看到,在对C进行实例化后,并没有立即进行初始化,而是先分别实例化了A和B。这说明,对象初始化之前需要先对该类及其父类实例化,这是符合直觉的,因为你可能在c的初始化过程中调用a或b的属性(赋零值的属性,暂未被显式初始化)或方法。
问题就在于,如果在C的 __init__
中调用super对父类初始化,那么这个super到底指谁呢?
这就涉及到python的 Method Resolution Order(MRO)机制 了,这里的super指的其实是a
MRO是一个列表,它反映了多继承下,方法的查找顺序,可以通过 class.mro()
方法进行查看
print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
该列表中,下一个元素就是上一个元素的super,所以,对C来说,其super指的就是A,当初始化代码执行到A时,对A来说,其super指的就是B,对B来说,其super自然就是object了。这一点就是不符合直觉的,并且会造成很多很多的问题,例如钻石型继承关系、重载等问题,在java中,只允许单继承就不会有这种问题了。
当然,上述C、A、B的 __init__
不执行super的初始化也是没关系的,因为类在实例化时父类也被实例化过了,其属性(不是定义在init函数中的,例如上述代码中的 a_attr)也被赋予了零值或初始值,也就可以正常调用父类的属性和方法的