【问题标题】:Method overriding about inheritance Python关于继承Python的方法覆盖
【发布时间】:2019-05-03 20:12:50
【问题描述】:

我正在阅读 python 3.7 文档。我对以下句子感到很困惑:


“派生类可能会覆盖其基类的方法。由于方法在调用同一对象的其他方法时没有特殊权限,因此基类的方法调用同一基类中定义的另一个方法可能最终会调用一个覆盖它的派生类的方法。(对于 C++ 程序员:Python 中的所有方法实际上都是虚拟的。)"


您能否给我看一个示例代码,说明“调用同一基类中定义的另一个方法的基类最终可能会调用覆盖它的派生类的方法。”? 这是我的理解:

class A:
def me(self):
    print("This is A")

def idet(self):
    self.me()


class B(A):
    def me(self):
        print("this is B")


a = A()
b = B()
b.me()
b.idet()

结果是

this is B
this is B

我不确定是不是这样。

最后一个问题是“Python 中的所有方法实际上都是虚拟的”是什么意思? (我熟悉Java但不熟悉C++)

【问题讨论】:

    标签: python inheritance methods overriding


    【解决方案1】:

    这个例子正好说明了这个原则。 bB 的一个实例,它调用类A 中定义的方法ident,而后者又调用me。由于B 覆盖meB 的方法被调用,你得到this is me 打印出来。

    在 C++ 中,默认情况下不能覆盖方法 - 您必须将它们声明为 virtual 才能获得此行为。在 Python 中(以及在 Java 中,你提到你很熟悉)这是默认行为。在 Java 中,您可以修改方法,使其不能被覆盖,方法是将其定义为 final

    【讨论】:

    • 所以这些陈述只是描述了像Java这样的覆盖的基本机制。 python的覆盖有什么java没有的特殊功能吗?
    【解决方案2】:

    当你派生一个类时,超类的所有方法都被复制到基类中。当您在基类(或超类)中定义方法的同时重新定义超类中已经存在的方法时,它被称为覆盖。当您在子类中覆盖基类(或超类)中的方法时,它会切断基类中的方法与子类之间的联系。

    在你的程序中,你首先调用b.me(),这是一个被覆盖的方法;因此,它将执行 B 类中的 me()。然后,你得到了b.idet(),它是从基类A 复制的方法;所以,它的代码不会改变。但是,当您仔细查看 idet() 方法的主体时,它所做的是它将调用正在调用它的类的 me() 方法。在这种情况下,由于调用该方法的类是类B,它将执行类B 中的me() 方法。

    idet() 得到了self.me()self 关键字引用了它所在的属性/方法类。

    【讨论】:

      【解决方案3】:

      我认为 Python3 文档也可能提到,当 B 类的实例“b”引用从 A 类中提取的方法时,它会传递自身 作为第一个参数(self)进入该方法。因此,任何在 'b' 调用的 any 方法(包括其继承的方法)中对“self”的引用将首先在 A 类函数之前搜索 B 类函数,即使 'b' 调用的方法是派生的来自A班。

      b.idet() 等价于调用b.me()A.idet(b)

      "一个基类的方法调用另一个定义在 相同的基类可能最终会调用派生类的方法来覆盖它”

      我可以看出这似乎具有误导性,我认为这是因为基类 A 的方法 idet(self) 仅在“self”引用 A 的实例时才调用同一基类 (A) 中定义的另一个方法,但是在上述场景中,当“self”引用子类 B 的实例时,idet(self) 并没有真正调用 A 中定义的另一个方法,而是调用 B 中定义的覆盖 A 的方法。 p>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-07
        • 2012-09-27
        • 1970-01-01
        • 2012-11-20
        • 2016-06-04
        • 2016-01-25
        • 1970-01-01
        • 2011-06-14
        相关资源
        最近更新 更多