繁体   English   中英

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

[英]What is the correct way to extend a parent class method in modern Python

我经常做这样的事情:

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(self) 行似乎不正确。 如果我要更改 class Waiter 从中继承的内容,我将不得不追踪其中的每一个并将它们全部替换。

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

如果有任何问题,我通常坚持使用单个 inheritance,但如果需要额外的东西来正确容纳多个 inheritance,那么了解这一点会很好。

你用super

返回将方法调用委托给父类或兄弟类类型的代理对象。 这对于访问已在类中重写的继承方法很有用。 搜索顺序与getattr()使用的搜索顺序相同,只是跳过了类型本身。

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

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

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

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

super(Waiter, self).greet()

这将调用Persongreet()函数。

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

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

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

我想通过一个例子在这个答案中更明确地说明这一点。 这就像我们在 JavaScript 中所做的一样 简短的回答是,就像我们使用super启动构造函数一样。

class Person(object):                                                             
   def __init__(self, name):                                                      
       self.name = name                                                           
                                                                                    
   def greet(self):                                                               
       print(f"Hello, I'm {self.name}")                                           
                                                                                    
class Waiter(Person):                                                             
    def __init__(self, name):                                                     
        super().__init__(name)
        # initiate the parent constructor
        # or super(Waiter, self).__init__(name)                                                    
                                                                                    
    def greet(self):                                                              
        super(Waiter, self).greet()                                               
        print("Would you like fries with that?")                                  
                                                                                    
waiter = Waiter("John")                                                           
waiter.greet()

# Hello, I'm John
# Would you like fries with that?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM