子类中调用继承方法的区别?

0 投票
3 回答
1508 浏览
提问于 2025-04-16 12:26

对于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 这个调用方式可以确保调用的是 Afoo 方法,而不是 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)则是直接调用那个特定的方法。

撰写回答