在本教程中,我们将学习方法解析顺序,也称为MRO(Method Resolution Order)。这是Python继承的一个重要概念。

方法解析顺序描述了Python用于在包含多重继承的类中获取适当方法的搜索路径。

简介

我们知道,被继承的类称为子类或父类,而继承的类称为子类或子类。在多重继承中,一个类可以包含许多方法,因此使用方法解析顺序技术来搜索执行基类的顺序。

简而言之 - "如果当前类中不存在方法或属性,则搜索将移至父类,依此类推"。这是深度优先搜索的一个示例。

在多重继承中发挥了重要作用,其中同一个方法可以在多个超类中找到。

为了更好地理解它,让我们看看如何使用它。

示例 -

class A:  
    def myname(self):  
        print("I am a class A")  
  
class B(A):  
    def myname(self):  
        print("I am a class B")  
  
class C(A):  
    def myname(self):  
        print("I am a class C")   
c = C()  
print(c.myname())  

输出:

I am a class C

解释 -

上面的代码中存在多重继承。我们定义了三个类A、B和C,这些类具有相同名称的方法myname()。我们创建了一个C类的对象。对象调用了C类,而不是A类,尽管C类继承了A类的方法。

上述代码中的顺序是B类->A类。这种技术称为MRO(方法解析顺序)。

让我们了解另一个多重继承的示例。

示例 -

class A:  
    def myname(self):  
        print(" I am a class A")  
class B(A):  
    def myname(self):  
        print(" I am a class B")  
class C(A):  
    def myname(self):  
        print("I am a class C")  
  
# classes ordering  
class D(B, C):  
    pass      
d = D()  
d.myname()  

输出:

I am a class B

解释 -

在上面的代码中,我们创建了另一个D类,没有定义继承了B和C类的类属性。当我们调用myname()方法时,它会转到D类并搜索myname()函数。但是D类没有任何声明。因此,搜索会传递到B类,获取myname()函数并返回结果。搜索将按以下方式进行。

Class D -> Class B -> Class C -> Class A  

如果B类没有方法,它将调用C类的方法。

在这里,我们建议您移除B类的方法并查看会发生什么。通过这样做,您将了解方法解析的工作原理。

旧版和新版顺序

在旧版Python(2.1)中,我们受限于使用旧类,但在Python(2.2及更高版本)中,我们可以使用新类。默认情况下,Python 3具有原始(新)类。新样式类的第一个父类继承自Python根的'object'类。让我们看看以下示例 -

示例 -

# Old style class  
class OldStyleClass:  
    pass  
  
# New style class  
class NewStyleClass(object):  
    pass 

这两个类的声明样式不同。在方法解析中,旧样式类遵循深度优先从左到右的算法(DLR),而新样式类在执行多重继承时使用C3线性化算法。

DLR算法

Python在实现类之间的多重继承时会创建一个类列表。该列表用于确定在实例调用时应调用哪个方法。

我们可以通过其名称来假定它的工作原理,因为方法解析会深度优先搜索,然后从左到右搜索。以下是示例。

示例 -

class A:  
    pass  
class B:  
    pass  
class C(A, B):  
    pass  
class D(B, A):  
    pass  
class E(C,D):  
    pass  

首先,该算法将在实例类中搜索被调用的方法。如果未找到,则进入第一个父类,如果也未找到,则查找父类的父类。这将一直持续到继承类的末尾。

在上面的示例中,方法解析顺序将是 -

class D -> class B -> class A -> class C -> class A  

但是,A不能出现两次,因此 -

class D -> class B -> class A -> class C ->  

该算法在某些情况下表现出奇怪的行为。让我们看下面的示例。

示例 -

class A:   
    pass  
  
class B:  
    pass  
  
  
class C(A, B):   
    pass  
  
class D(B, A):   
    pass  
  
class E(C,D):  
    pass  

根据DLR算法,顺序将是E、C、D、B、A。在类C中A和B的顺序互换,这非常模糊。这意味着该算法不保留单调性属性。

Samuele Perdoni是第一个发现MRO算法之间的不一致性的人。

C3线性化算法

C3线性化算法是DLR算法的改进版本,因为它消除了不一致性。该算法具有一些限制,如下所示。

  • 子类必须在父类之前。
  • 如果某个类继承自一个或多个类,它们以基类元组中指定的顺序保存。

C3线性化算法的规则

  • 方法解析顺序的结构由继承图定义。
  • 用户必须在访问本地类的方法后访问超类。
  • 保持单调性

方法解析类的方法

Python提供了两种获取类的方法解析顺序的方法 - mro属性或mro()方法。使用这些方法,我们可以显示它们解析的方法顺序。

让我们了解以下示例。

示例 -

class A:  
    def myname(self):  
        print(" I am a class A")  
class B(A):  
    def myname(self):  
        print(" I am a class B")  
class C(A):  
    def myname(self):  
        print("I am a class C")  
  
# classes ordering  
class D(B, C):  
    pass      
  
  
# it prints the lookup order  
print(D.__mro__)  
print(C.mro())  

输出:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
[<class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

正如我们在上面的输出中看到的那样,我们获得了方法解析顺序的顺序。这样,C3线性化算法可以用于多重继承。

标签: Tkinter教程, Tkinter安装, Tkinter库, Tkinter入门, Tkinter学习, Tkinter入门教程, Tkinter, Tkinter进阶, Tkinter指南, Tkinter学习指南, Tkinter进阶教程, Tkinter编程