在现代Python中扩展父类方法的正确方法是什么

时间:2011-05-20 10:29:52

标签: python inheritance

我经常这样做:

class Person(object):
    def greet(self):
        print "Hello"

class Waiter(Person):
    def greet(self):
        Person.greet(self)
        print "Would you like fries with that?"

线Person.greet(自我)似乎不对。如果我改变了Waiter继承的类,我将不得不追踪其中的每一个,并将它们全部替换掉​​。

现代Python的正确方法是什么? 2.x和3.x都有,我知道3中这个区域有变化。

如果重要的话我通常坚持单继承,但是如果需要额外的东西来正确地适应多重继承,那么了解它就好了。

3 个答案:

答案 0 :(得分:20)

您使用super

  

返回委派的代理对象   方法调用父或兄弟   类型。这很有用   访问具有的继承方法   在课堂上被覆盖了。搜索   顺序与使用的顺序相同   getattr()除了类型本身   被跳过了。

换句话说,对super的调用会返回一个伪对象,该对象将属性查找委托给继承链中的上面的类。注意事项:

  • 这不适用于旧式类 - 因此,如果您使用的是Python 2.x,则需要确保层次结构中的顶级类继承自object
  • 您需要将自己的类和实例传递给Python 2.x中的super。此要求在3.x中免除。
  • 这将正确处理所有多重继承。 (如果在Python中有多重继承树,则会生成method resolution order,并且查找按此顺序通过父类。)

注意:有很多地方对Python中的多重继承感到困惑。您可能需要阅读super() Considered Harmful。如果您确定要坚持使用单个继承树,并且不打算更改所述树中类的名称,则可以像上面那样对类名进行硬编码,一切都会正常工作。

答案 1 :(得分:9)

不确定你是否正在寻找这个,但你可以通过这样做来打电话给父母而不参考它。

super(Waiter, self).greet()

这将调用greet()中的Person功能。

答案 2 :(得分:4)

katrielalex的回答确实是你问题的答案,但这不符合评论。

如果您计划到处使用super,并且您曾考虑过多重继承,请务必阅读“super()Considered Harmful”链接。 super()是一个很棒的工具,但要正确使用它需要理解。根据我的经验,对于似乎不太可能进入复杂钻石继承纠缠的简单事物,直接调用超类并在更改基类名称时处理重命名实际上更简单,更乏味。

实际上,在Python2中,您必须包含当前的类名,它通常比基类名更改。 (事实上​​,如果你正在做古怪的事情,有时很难将引用传递给当前类;在定义方法时,类没有绑定任何名称,并且在{调用{1}}执行该类的原始名称可能仍未绑定到该类,例如当您使用类装饰器时)