Python 为什么在这里从基类调用子方法?

Python 为什么在这里从基类调用子方法?,python,inheritance,super,Python,Inheritance,Super,当我从基类的\uuu init\uuuu()方法调用childs方法时,我不理解为什么在这里调用它: class base(): def __init__(self, x): self.set_state(x) def set_state(self, x): self.x = x print("base") class child(base): def __init__(self, x, y): supe

当我从基类的
\uuu init\uuuu()
方法调用childs方法时,我不理解为什么在这里调用它:

class base():
    def __init__(self, x):
        self.set_state(x)

    def set_state(self, x):
        self.x = x
        print("base")

class child(base):
    def __init__(self, x, y):
        super().__init__(x)
        self.set_state(y)

    def set_state(self, y):
        self.y = y
        print("child")

test = child(1, 2)
输出为:

child
child

这对于所有多态语言都是通用的。多态性的定义是,对象的实际(最派生的)类型决定调用哪个版本的方法,即使在调用点您只知道它是某个超类的实例


如果您需要重写此方法,并且绝对只从超类init调用超类方法,请使用两个前导下划线将其命名为
\uu set\u state
。这会调用pythons名称混乱规则,这样子类就不能(轻松地)重写该方法——但是,它也会使它无法从外部代码调用(或者不容易调用)。但是多态行为通常是你想要的,这就是为什么它是Python中的默认值(而不是说,C++中,方法不是多态的,除非你明确地声明它们是“代码>虚拟< /代码>”。

< P>这是所有多态语言都常见的。多态性的定义是,对象的实际(最派生的)类型决定调用哪个版本的方法,即使在调用点您只知道它是某个超类的实例


如果您需要重写此方法,并且绝对只从超类init调用超类方法,请使用两个前导下划线将其命名为
\uu set\u state
。这会调用pythons名称混乱规则,这样子类就不能(轻松地)重写该方法——但是,它也会使它无法从外部代码调用(或者不容易调用)。但是多态行为通常是你想要的,这就是为什么它是Python中的默认值(与C++相反,在这里,方法不是多态的,除非你明确地声明它们是“代码>虚拟< /代码>”。
self
变量是
child
对象的名称,因此当您在
self
上查找名称
set\u state
时,会得到
child.set\u state
(绑定到
self
)。如果您来自另一种语言:python中的所有方法都是虚拟的。这不是一个滑稽的问题。如果你能解释一下你头脑中的模型,它会让你期待其他任何事情发生,那么我们也许可以解释你在哪里感到困惑。但是没有这些,我有点困惑。除非你来自,比如说C++,只是不知道Python不需要一个代码>虚拟< /Cord>关键字,因为所有的方法都是虚拟的,或者类似的东西,并且添加到@ ALAN FY的评论中,如果你来自不同的语言,您可能也希望在构造函数中调用虚拟方法时小心(并不是说
\uuu init\uuu
实际上是Java/C意义上的构造函数)。例如,你会的。这就是继承的工作原理。为什么不叫它呢?
self
变量是
child
对象的名称,因此当您在
self
上查找名称
set\u state
时,会得到
child.set\u state
(绑定到
self
)。如果您来自另一种语言:python中的所有方法都是虚拟的。这不是一个滑稽的问题。如果你能解释一下你头脑中的模型,它会让你期待其他任何事情发生,那么我们也许可以解释你在哪里感到困惑。但是没有这些,我有点困惑。除非你来自,比如说C++,只是不知道Python不需要一个代码>虚拟< /Cord>关键字,因为所有的方法都是虚拟的,或者类似的东西,并且添加到@ ALAN FY的评论中,如果你来自不同的语言,您可能也希望在构造函数中调用虚拟方法时小心(并不是说
\uuu init\uuu
实际上是Java/C意义上的构造函数)。比如说,你会的。你比我抢先一步:好的,谢谢你,那真的很有帮助。我显然误解了super()的工作原理,我认为这不仅会迫使调用的方法来自基类,还会迫使所有后续调用都来自基类。我显然误解了super()的工作原理,我认为它不仅会强制调用基类中的方法,还会强制所有后续调用。