浅谈Python面向对象中的继承与mro

1,386 阅读3分钟

我正在参加「掘金·启航计划」

继承

python中的继承的含义就是其字面意思, 子类继承父类中的属性和方法, 且可以同时继承多个父类, 子类下面还可以再继续划分子类的子类。形成一种树形的结构, 最顶部的类叫做基类, 基类下面的子类等被称为派生类
在子类中可以定于跟父类中名称相同的方法和属性, 这些行为被称之为重写(重构), 在调用时优先调用当前类中的方法, 如果在当前类中搜索不到则树形结构向上递归查找。
PS: Python中所有的类都默认继承一个基类 Object


class A: # 等价于 class A(Object):
    def __init__(self, name):
        self.name = name

    def run(self):
        return "running with class A"


class B:
    def __init__(self, name):
        self.name = name

    def run(self):
        return "running with class B"

class C(B, A):

    def space(self):
        pass

# a既是C的实例, 也是A,B的实例
a = C("takahashi")

# 按mro结构查找方法
print(a.run())

>>> running with class B

Mro

Python的MRO即Method Resolution Order(方法解析顺序),即在调用方法时,会对当前类以及所有的基类进行一个搜索,以确定该方法之所在,而这个搜索的顺序就是MRO。

Mro搜索原则:

  1. 子类永远在父类前面
    2. 如果有多个父类,则按mro列表中的顺序被调用
    3. 如果下一个类中存在两个合法的选择, 则只选择第一个

如果需要查看类的mro调用顺序只需要打印ClassName.mro()即可, 返回一个列表。

示例代码


class A:

    def __init__(self):
        print("Class A now is start!")

class B(A):

    def __init__(self):
        super().__init__() # 此处先调用了class A中的__init__方法
        print("Class B now is start!")

class C:

    def __init__(self):
        print("Class C now is start!")


class inherit(A, C):
    def display(self):
        print(inherit.mro())


class other_inherit(B, C):
    def display(self):
        print(other_inherit.mro())


class another_inherit(C, B):
    def display(self):
        print(another_inherit.mro())

class last_inherit(other_inherit, C):
    def display(self):
        print(last_inherit.mro())



print("----------------------cut-line-----------------------")
a = inherit()
a.display()
print("----------------------cut-line-----------------------")
b = other_inherit()
b.display()
print("----------------------cut-line-----------------------")
c = another_inherit()
c.display()
print("----------------------cut-line-----------------------")
d = last_inherit()
d.display()
print("----------------------cut-line-----------------------")
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> [<class '__main__.inherit'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> Class B now is start!
>>> [<class '__main__.other_inherit'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class C now is start!
>>> [<class '__main__.another_inherit'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> Class B now is start!
>>> [<class '__main__.last_inherit'>, <class '__main__.other_inherit'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------

super()

并非魔术方法, 但是在Python对象的创建和父类(同胞类, 下略)函数的调用中起到了至关重要的作用

函数结构

super(ClassName, Type).function(Type, [*args...])

函数作用

提供对父类或者同胞类中的方法和属性的访问

说明

在Python3中super默认值是当前继承的父类名, 如果有多个继承的父类, 则取第一个。
如果继承的多个父类中都有着相同的方法则只调用第一个继承的父类中的那个方法。


class A:

    def __init__(self):
        print("Class A now is start!")

class B(A):

    def __init__(self):
        super().__init__()
        print("Class B now is start!")

class C:

    def __init__(self):
        print("Class C now is start!")

class D:
    def __init__(self):
        print("Class D now is start!")
class inherit(A, C):
    def display(self):

        print(inherit.mro())


class other_inherit(B, C):
    def display(self):

        print(other_inherit.mro())


class another_inherit(A, D):
    def display(self):

        print(another_inherit.mro())

class last_inherit(other_inherit, C):
    def display(self):

        print(last_inherit.mro())
        
class test(last_inherit, another_inherit):
    def display(self):
        print(super().display())


print("----------------------cut-line-----------------------")
a = inherit()
a.display()
print("----------------------cut-line-----------------------")
b = other_inherit()
b.display()
print("----------------------cut-line-----------------------")
c = another_inherit()
c.display()
print("----------------------cut-line-----------------------")
d = last_inherit()
d.display()
print("----------------------cut-line-----------------------")
e = test()
e.display()

print("----------------------cut-line-----------------------")
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> [<class '__main__.inherit'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> Class B now is start!
>>> [<class '__main__.other_inherit'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> [<class '__main__.another_inherit'>, <class '__main__.A'>, <class '__main__.D'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> Class B now is start!
>>> [<class '__main__.last_inherit'>, <class '__main__.other_inherit'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> ----------------------cut-line-----------------------
>>> Class A now is start!
>>> Class B now is start!
>>> [<class '__main__.last_inherit'>, <class '__main__.other_inherit'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
>>> None
>>> ----------------------cut-line-----------------------

由上可得, 如果同时继承了多个父类, 则在调用父类中的方法时只会调用第一个继承的父类中的方法。