python - 在使用 OOP 尝试钻石形状问题时,Python 中发生了什么

标签 python python-3.x class inheritance polymorphism

我正在用 python 学习 OOP。创建以下代码来复制多重继承中的菱形问题。我在 jupyter 笔记本中运行以下代码,并同时生成输出。

class parent:
    def __init__(self):
        self.a=2
        self.b=4
    def form1(self): 
        print("calling parent from1")
        print('p',self.a+self.b)

class child1(parent):
    def __init__(self):
        self.a=50
        self.b=4
    def form1(self):
        print('bye',self.a-self.b)
    def callchildform1(self):
        print("calling parent from child1")
        super().form1()

class child2(parent):
    def __init__(self):
        self.a=3
        self.b=4
    def form1(self):
        print('hi',self.a*self.b)
    def callchildform1(self):
        print("calling parent from child2")
        super().form1()

class grandchild(child1,child2):
    def __init__(self):
        self.a=10
        self.b=4
    def callingparent(self):
        super().form1()

g=grandchild()
g.form1()
g.callchildform1()
g.callingparent()

输出如下

bye 6
calling parent from child1
hi 40
bye 6

我可以理解两次“bye 6”输出,但它是如何打印“hi 40”的。我是新人,所以任何人都可以解释这里发生的事情。

最佳答案

您可能会发现类的 __mro__ 属性提供了丰富的信息。在这里,MRO 代表M方法R解决方案O顺序。

考虑对您的代码进行此修改:

class Parent:
    def __init__(self):
        self.a = 2
        self.b = 4

    def print_name(self):
        print("parent")

    def form1(self):
        print("calling parent form1")
        print('p', self.a + self.b)


class Child1(Parent):
    def __init__(self):
        self.a = 50
        self.b = 4

    def print_name(self):
        print("child1")

    def print_super_name(self):
        super().print_name()

    def form1(self):
        print('bye', self.a - self.b)

    def callchildform1(self):
        print("calling parent from child1")
        super().form1()


class Child2(Parent):
    def __init__(self):
        self.a = 3
        self.b = 4

    def print_name(self):
        print("child2")

    def form1(self):
        print('hi', self.a * self.b)

    def callchildform1(self):
        print("calling parent from child2")
        super().form1()


class Grandchild(Child1, Child2):
    def __init__(self):
        self.a = 10
        self.b = 4

    def print_name(self):
        print("grandchild")

    def print_super_name(self):
        super().print_name()

    def print_super_super_name(self):
        super().print_super_name()

    def callingparent(self):
        super().form1()


g = Grandchild()
print("When I print the name of my class it is:")
g.print_name()
print("When I print my superclass name, it is:")
g.print_super_name()
print("When I print the name of the superclass of my superclass, it is:")
g.print_super_super_name()
print("When you call methods on me, they will be executed from my class and my parent classes in the following order:")
print(Grandchild.__mro__)
g.form1()
g.callchildform1()
g.callingparent()

输出为:

When I print the name of my class it is:
grandchild
When I print my superclass name, it is:
child1
When I print the name of the superclass of my superclass, it is:
child2
When you call methods on me, they will be executed from my class and my parent classes in the following order:
(<class '__main__.Grandchild'>, <class '__main__.Child1'>, <class '__main__.Child2'>, <class '__main__.Parent'>, <class 'object'>)
bye 6
calling parent from child1
hi 40
bye 6

当您运行g.callchildform1()时,Python 会在Grandchild 中查找callchildform1 的定义。它不在那里,因此它查找的下一个位置是 Child1。您可以从示例和方法解析顺序中看到,当 Grandchild 的实例调用 Child1 中定义的方法时,该方法会调用 super() ,对被调用方法的搜索将从 Child2 开始。

关于python - 在使用 OOP 尝试钻石形状问题时,Python 中发生了什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53615536/

相关文章:

python - 如何在 python 中创建顺序组合列表?

Python 3 - 类型错误 : can only concatenate str (not "bytes") to str

java - 如何在 UML 中对枚举进行建模,以便它们表达键值关系?

python - 恢复 matplotlib 默认轴刻度

python - mixins 应该使用父属性吗?

python - Ansible + Ubuntu 18.04 + MySQL = "The PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) module is required."

python - 枪兽 : Failed to find application object 'App' in 'run'

python - 将excel中的数据粘贴到网站,点击 "track"

c++ - 将类型参数传递给自引用指针

C++专门化模板类函数而无需重复代码