Method Resolve Order (MRO) - 类对象属性的解析顺序


Method Resolve Order (MRO) - 类对象属性的解析顺序
Python 支持多重继承, 此时就需要解决按照何种顺序来解析属性的问题.类的继承关系在一个特殊的类属性中指定(__mro__).这个属性的作用是按照序列出类及其超类, python 会按照这个顺利搜索方法。任何实现了多重继承的语言都要处理潜在的命名冲突问题,这种冲突由不相关的父类实现的同名方法所引起的,称为‘菱形问题‘。

举个例子,
 1 class A(list):
 2     def disp(self):
 3         print(‘Class A - disp‘)
 4
 5 class B(list):
 6     def disp(self):
 7         print(‘Class B - disp‘)
 8
 9     def dispB(self):
10         print(‘Class B - dispB‘)
11
12 class C(A):
13     pass
14
15 class D(C, B):
16     pass
17
18 if __name__ == ‘__main__‘:
19     abc = D()
20     abc.disp()
21     abc.dispB()
22     print(D.__mro__)
23     print(C.__mro__)
24     print(B.__mro__)
25     print(A.__mro__)
26
27 ‘‘‘
28 Output,
29     Class A - disp
30     Class B - dispB
31     (<class ‘__main__.D‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
32     (<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)
33     (<class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)
34     (<class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)
35 ‘‘‘
D 的基类都实现了 disp 方法。当实例 abc 调用 disp() 方法的时候,是运行 A 或者 B 中的 disp 方法呢?Python 内部首先完成对 D 这个类的 MRO 顺序的建立. 这个顺序存储在 D.__mor__ 属性中, 其为一个 tuple 对象,依次存放着 class 对象. 这个 tuple 中 class 对象的顺序就是 Python 虚拟机在解析 D 这个类的属性时的顺序。最终这个 tuple 将被保存在 PyTypeObject.tp_mro 中.

示例中各个类的继承顺序,    D -> C -> A -> B -> list -> object    C -> A -> list -> object    B -> list -> object    A -> list -> object

即,    (<class ‘__main__.D‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)    (<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)    (<class ‘__main__.B‘>, <class ‘list‘>, <class ‘object‘>)    (<class ‘__main__.A‘>, <class ‘list‘>, <class ‘object‘>)

注, MRO 设计到 ‘深度优先‘ 和 ‘广度优先‘ 两个概念.可以把这两个概念想象成两个维度. 深度优先 为 纵向维度, 广度优先 为 横向维度.

以示例为例,        D - C     - B     - list      - object            |       |       |           |            A       list    object      object            |       |            list    object            |            object

在 横向上(广度优先概念), 如果实例 abc 调用 disp 方法, 最终会运行 class B 中的 disp 属性.        在 纵向上(深度优先概念), 如果实例 abc 调用 disp 方法, 最终会运行 class A 中的 disp 属性.        即 MRO 为 深度优先搜索
				
时间: 2024-09-29 01:58:29

Method Resolve Order (MRO) - 类对象属性的解析顺序的相关文章

Method Resolution Order – Python类的方法解析顺序

在支持多重继承的编程语言中,查找方法具体来自那个类时的基类搜索顺序通常被称为方法解析顺序(Method Resolution Order),简称MRO.(Python中查找其它属性也遵循同一规则.)对于只支持单重继承的语言,MRO十分简单:但是当考虑多重继承的情况时,MRO算法的选择非常微妙.Python先后出现三种不同的MRO:经典方式.Python2.2 新式算法.Python2.3 新式算法(也称作C3).Python 3中只保留了最后一种,即C3算法. 经典类采用了一种简单MRO机制:查

python类对象属性查找原理

class Foo(object): def __init__(self): # 这是一个对象属性 self.obj_pro = 12 # 这是一类属性 c_pro = 11 # 这是一个静态方法 @classmethod def c_method(self): print('c_method') if __name__ == '__main__': f = Foo() """ 如何查找对象属性? 就是在对象的__dict__字典去找,对象__dict__找不到,再去类__d

object-c计划tips-添加到类对象属性

这个问题从网络包的内容,由于保密问题,我刚才所描述我的业余的想法. 基本的想法: 网络请求,我们应该能够使用基类BaseNetWork, 然后由派生类继承BaseNetWork,并实现一些特殊的方法. 一般标准的流程是传入block, 当网络请求完成后.通过block回调回来.这里叙述的关键不是怎样实现一个网络请求和回调block的相关内容,而是怎样取消请求. 一般基类会实现一个cancelNetWork方法.它依据自己的url进行cancel操作. 举例: 我们使用 DerivedNetWor

TypeError: Error when calling the metaclass bases Cannot create a consistent method resolution order (MRO) for bases A2, A1 出现原因及其解决办法

原本想测试继承,出现了这个错误: 源代码 1 class A1(object): 2 def fo1(self): 3 print "i'm A1" 4 class A2(object): 5 def fo1(self): 6 print "i'm A2" 7 class B1(A1,A2): 8 def bar(self): 9 print "i'm B1" 10 class B2(A2,A1): 11 def bar(self): 12 pr

Objective-C对象之类对象和元类对象

作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/8592492 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号wangzzstrive来支持我,谢谢! 作为C语言的超集,面向对象成为Objective-C与C语言的最大区别,因此,对象是Objective-C中最重要的部分之一.目前面向对象的语言有很多,Objective-C中的对象又和其他语言中的对象有什么区别呢?下面来简单介绍Objectiv

对象属性的可枚举性

JavaScript中对象的属性分为两种:数据属性和访问器属性.然后根据具体的上下文环境的不同,又可以将属性分为:原型属性和实例属性.原型属性是定义在对象的原型(prototype)中的属性,而实例属性一方面来自构造的函数中,然后就是构造函数实例化后添加的新属性. 在JavaScript中除了检测对象的属性是否存在,还会经常对对象的属性进行遍历(枚举).而在JavaScript中遍历一个对象的属性并不太简单,主要有两个原因: JavaScript中的对象通常都处在某个原型链中,它会从一个或多个的

创建java类并实例化类对象

创建java类并实例化类对象例一1.面向对象的编程关注于类的设计2.设计类实际上就是设计类的成员3.基本的类的成员,属性(成员变量)&方法 面向对象思想的落地法则一:1.设计类,并设计类的成员(成员变量&成员方法)2.通过类,来创建类的对象(也称作类的实例化) public class zoo { public static void main(String[] args) { //基本数据类型的声明,数据类型 变量名=初始化值 //类的实例化:如a1就是一个对象 Animal a1=ne

组合,Mixin,类、类对象、实例对象

1.组合,将几个横向关系的组合在一起.所谓的组合就是将类的实例化放到新类里面,那么就将旧类组合进去了. class Turtle: def __init__(self, x): # 注意 init 前面必须双下划线 self.num = x class Fish: def __init__(self, x): self.num = x class Pool: def __init__(self, x, y): self.turtle = Turtle(x) # Pool类中实例化Turtle对象

福利-&gt;KVC+Runtime获取类/对象的属性/成员变量/方法/协议并实现字典转模型

我们知道,KVC+Runtime可以做非常多的事情.有了这个,我们可以实现很多的效果. 这里来个福利,利用KVC+Runtime获取类/对象的所有成员变量.属性.方法及协议: 并利用它来实现字典转模型. 废话不多说,直接上代码: 1.工具类(其实就是NSObject的一个分类)头文件 1 #import <Foundation/Foundation.h> 2 3 @interface NSObject (YSRuntime) 4 5 /** 6 返回当前类的属性数组 7 8 @return 属