昨天在Python类的多重继承那里纠结了好久,在提问版块提了个问题探讨了探讨(链接)才完全搞明白,现在把类的特性整理下,供以后参考
首先得说明的是,Python的类分为经典类 和 新式类
经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了
新式类在python2.2之后的版本中都可以使用
object这个基类的:| 123456 | # old styleclass A():pass # new styleclass A(obejct):pass |
2.经典类在类多重继承的时候是采用从左到右深度优先原则匹配方法的..而新式类是采用C3算法(不同于广度优先)进行匹配的
3.经典类是没有__MRO__和instance.mro()调用的,而新式类是有的.
因为在经典类中的多重继承会有些问题…可能导致在继承树中的方法查询绕过后面的父类:
| 123456789101112131415 | class A(): def foo1(self): print \”A\”class B(A): def foo2(self): passclass C(A): def foo1(self): print \”C\”class D(B, C): pass d = D()d.foo1() |
按照经典类的查找顺序从左到右深度优先的规则,在访问d.foo1()的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过.
所以python引入了新式类的概念,每个基类都继承自object并且,他的匹配规则也从深度优先换到了C3
C3算法是怎么做匹配的呢..在问答版块上面讨论之后,归结如下:
C3算法的一个核心是merge.
在merge列表中,如果第一个序列mro的第一个类是出现在其它序列,并且也是第一个,或者不出现其它序列,那么这个类就会从这些序列中删除,并合到访问顺序列表中
比如:(引用问题中zhuangzebo的回答@zhuangzebo)
| 123456 | class A(O):passclass B(O):passclass C(O):passclass D(A,B):passclass E(C,D):pass |
首先需要知道 O(object)的mro(method resolution order)列表是[O,]
那么接下来是:
| 123456789101112131415 | mro(A) = [A, O]mro(B) = [B, O]mro(C) = [C, O]mro(D) = [D] + merge(mro(A), mro(B), [A, B])= [D] + merge([A, O], [B, O], [A, B])= [D, A] + merge([O], [B, O], [B])= [D, A, B] + merge([O], [O])= [D, A, B, O]mro(E) = [E] + merge(mro(C), mro(D), [C, D])= [E] + merge([C, O], [D, A, B, O], [C, D])= [E, C] + merge([O], [D, A, B, O], [D])= [E, C, D] + merge([O], [A, B, O])= [E, C, D, A, B] + span>C, D, A, B] + > 经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了 新式类在python2.2之后的版本中都可以使用 经典类和新式类的区别在于:
2.经典类在类多重继承的时候是采用 3.经典类是没有 为什么不用经典类,要更换到新式类因为在经典类中的多重继承会有些问题…可能导致在继承树中的方法查询绕过后面的父类:
按照经典类的查找顺序 所以python引入了新式类的概念,每个基类都继承自 C3算法C3算法是怎么做匹配的呢..在问答版块上面讨论之后,归结如下: C3算法的一个核心是
比如:(引用问题中zhuangzebo的回答@zhuangzebo)
首先需要知道 O(object)的
|
上一篇:众里寻她千百度,正则表达式
下一篇:使用python写vim插件