Python中的方法解析顺序

Python中的方法解析顺序

在本教程中,我们将了解方法解析顺序,也称为MRO。这是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的方法。

上述代码中的顺序为 **class B – > class 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线性化算法适用于多继承。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程