考虑以下代码:
class A:
def __init__(self):
print('class A is being constructed')
def print_msg(self):
print('Hello, I am class A')
class B(A):
def __init__(self):
super(B, self).__init__()
print('class B is being constructed')
def print_msg(self):
super(B, self).print_msg()
print('Hello, I am class B')
如您所见,每次调用super(B, self)
时都会调用B.print_msg()
。
我的问题是,每次我是这样做的,它是构造A的新对象,还是最初创建的对象,我每次都得到它的引用?
换句话说,下面的代码会构造A 100次吗?
b = B()
for i in range(100):
b.print_msg()
我开始怀疑它的原因是,在创建子对象时,不会自动调用父.__init__()
方法。
答案 0 :(得分:2)
super
不是函数;它实际上是一个类,其实例封装了有关所涉及类的方法解析顺序的知识。
super(B, self)
返回一个实例(一个代理对象),它知道任何类型self
具有的MRO,以及您希望在{{1}之间跳过MRO中的类的事实}和self.__class__
。当您在代理上调用方法时,它会找到要调用的正确方法,然后将B
作为参数传递给该方法。
假设对象self
是一个类self
的实例,其MRO看起来像A
。通常,拨打[A, C1, C2, C3, C4, B, C5, C6]
会检查A.foo()
是否有方法A
,如果没有,请继续按顺序检查foo
,C1
等直到它找到一个方法C2
的类。 foo
返回的代理基本上是“使用super(B, self)
的MRO”,这样当您编写[B, C5, C6]
时,如果super(B, self).foo()
没有,Python会直接跳至B
不存在。
在绝大多数情况下,A.foo
用于跳过实例的类本身,从MRO的前面修剪一个类。通过让您省略super
的参数,这是Python 3简化的行为。
答案 1 :(得分:1)
不,下面的代码将构造一个A恰好一次:
b = B()
for i in range(100):
b.print_msg()
这将隐含在行b = B()
中,因为B是A.
对象super(B, self)
是代理。它将使用类对象A
,但不需要实际创建A
的实例。