子类中调用继承方法的区别?
对于Python 2.5及以后的版本,使用新式类时,下面这段代码在子类中调用继承的方法有什么区别呢?
class A(object):
def foo(self):
pass
class B(A):
def __init__(self):
self.foo()
class C(A):
def __init__(self):
super(C, self).foo()
3 个回答
0
假设 B
自己定义了一个 foo
方法,那么 self.foo()
就会调用 B
的那个 foo
方法。可是在 C
的实现中,使用 super
这个调用方式可以确保调用的是 A
的 foo
方法,而不是 C
自己定义的 foo
方法。
0
区别在于,B
的子类可以正确地参与多态,因为如果它们重写了 foo()
方法,这个方法就会被调用。而 C
则没有这个选项。
1
只要你处理的是单继承的类,比如你给的例子,其实没什么太大区别。在这两种情况下,Python会用一种叫做方法解析顺序(mro)的规则来找出方法foo第一次出现的位置。你可以通过打印C.__mro__
来查看这个顺序。最终,这两种方式都会找到你基类A中的foo方法。
不过,当你开始使用多重继承时,事情就变得有趣了。看看下面这个例子:
class W(object):
def foo(self):
print "W"
class X(W):
def foo(self):
#super(X,self).foo()
W.foo(self)
print "X"
class Y(W):
def foo(self):
print "Y"
class Z(X,Y):
def __init__(self):
self.foo()
Z.__mro__
z = Z()
在类X中,我们可以用super来调用X的基类,也可以直接调用基类W。它们的区别在于,当使用super时,Python并不是找某个特定的实现,而是查找当前mro列表中的第一个实现。类Z的mro列表是:
(Z,X,Y,W)
因此,使用super的那一行会打印出:
Y
X
而直接调用基类的那一行会打印出:
W
X
简单来说,使用super会动态调用mro中找到的第一个实现,而用类.foo(或者在你的例子中用self.foo)则是直接调用那个特定的方法。