如何在Python中从子类调用父类的方法?

809 投票
16 回答
920126 浏览
提问于 2025-04-15 11:19

在Python中创建简单的对象层次结构时,我希望能够从子类调用父类的方法。在Perl和Java中,有一个专门的关键词来实现这个功能(super)。在Perl中,我可能会这样做:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}

而在Python中,似乎我必须在子类中明确指定父类的名字。在上面的例子中,我需要做类似Foo::frotz()的事情。

这让我觉得不太对,因为这种做法让构建复杂的层次结构变得困难。如果子类需要知道哪个类定义了一个继承的方法,那就会产生很多信息上的麻烦。

这真的是Python的一个限制,还是我理解上有问题,或者两者都有呢?

16 个回答

91
ImmediateParentClass.frotz(self)

无论直接的父类是自己定义了 frotz 还是从其他地方继承来的,这样都没问题。super 主要是为了支持多重继承(而且只有在每个类都正确使用它的情况下才能正常工作)。一般来说,如果 AnyClass 没有定义或覆盖 whatever,那么 AnyClass.whatever 会在 AnyClass 的祖先类中查找 whatever。这对于“子类调用父类的方法”来说也是一样的道理!

167

Python 里还有一个叫做 super 的东西:

super(类型[, 对象或类型])

这个东西会返回一个代理对象,它可以把方法调用转发给某个父类或兄弟类。 这在你想访问被覆盖的继承方法时特别有用。 查找的顺序和 getattr() 一样,只不过类型本身会被跳过。

举个例子:

class A(object):     # deriving from 'object' declares A as a 'new-style-class'
    def foo(self):
        print "foo"

class B(A):
    def foo(self):
        super(B, self).foo()   # calls 'A.foo()'

myB = B()
myB.foo()
1026

使用 super() 函数:

class Foo(Bar):
    def baz(self, **kwargs):
        return super().baz(**kwargs)

对于 Python 版本小于 3 的情况,你需要明确选择使用 新风格类,并且要使用:

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)

撰写回答