Code前端首页关于Code前端联系我们

Python 中的方法解析顺序

terry 2年前 (2023-09-29) 阅读数 64 #PHP
文章标签 PHP

在本教程中,我们将了解方法解析顺序,也称为 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,而不是类,类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 算法(DLR)进行方法解析,而新型类在执行多重继承时使用 C3 线性化算法。

动态链接库算法

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的交换,很不明确。这意味着该算法不保持单调性。

Samuel Pedoni 是第一个发现 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线性化算法就适合多重继承。


版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门