面试题答案
一键面试菱形继承场景
在Python多继承中,菱形继承指的是一个类从多个父类继承,而这些父类又有共同的祖先类,形成一个菱形结构。例如:
class A:
def method(self):
print("A's method")
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
这里 D
类继承自 B
和 C
,而 B
和 C
又都继承自 A
,形成菱形结构。
可能带来的问题
- 方法重复调用:当
D
类实例调用A
类中的方法(如method
)时,由于B
和C
都继承自A
,这个方法可能会被多次调用,导致不必要的开销和逻辑混乱。例如,如果A
类的method
方法中有资源初始化操作,就会重复执行这些操作。 - 继承路径不清晰:随着继承层次加深和菱形结构复杂,代码的维护和理解变得困难,很难确定某个方法或属性最终从哪个祖先类继承而来。
解决菱形继承问题的方法及原理
- 使用
super()
函数:- 原理:
super()
函数用于调用父类的方法,在Python 3中,它会按照特定的MRO(Method Resolution Order,方法解析顺序)来调用父类方法。MRO是一种线性化算法,它能确保每个类只被访问一次,避免重复调用。例如在上述菱形继承结构中,D
类实例调用method
方法时,super()
会按照MRO顺序(通常是D -> B -> C -> A
)来调用,保证A
类的method
方法只被调用一次。 - 示例:
- 原理:
class A:
def method(self):
print("A's method")
class B(A):
def method(self):
super().method()
class C(A):
def method(self):
super().method()
class D(B, C):
def method(self):
super().method()
d = D()
d.method()
- 采用新式类:
- 原理:Python 2中有经典类和新式类之分,Python 3中默认都是新式类。新式类采用C3线性化算法计算MRO,它能更合理地处理多继承中的菱形结构,确保方法解析顺序的一致性和合理性,避免重复调用祖先类方法等问题。
- 示例:在Python 3中,所有类默认都是新式类,无需额外操作。在Python 2中,需要显式继承
object
类来定义新式类。例如:
# Python 2示例
class A(object):
def method(self):
print("A's method")
class B(A):
def method(self):
super(B, self).method()
class C(A):
def method(self):
super(C, self).method()
class D(B, C):
def method(self):
super(D, self).method()
d = D()
d.method()