pythonmro函数 python chrom
11.详解python中super()函数原理及常用实例
type--类,object-or-type--类,一般是self
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、网页空间、营销软件、网站建设、淅川网站维护、网站推广。
运行发现:super().add(x) 与A.add(self,x)执行结果一致;但涉及多继承,发现super()只调用一次
在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照MRO(Method Resolution Order):方法解析顺序 进行的
super()可以调用父类中的任何方法,超(父类的父类)类的任何方法;可重写父类同名的 init 函数,及其他方法
在任何时候继承类和重写方法的,我们应当用到args, kwargs将接收到的位置参数和键值参数给父类方法
Python入门精华-OOP调用父类的方法及MRO方法解析序列
在继承关系中,我们想调用已经被覆盖了的父类的方法,就需要如下实现:
解决方法:
要调用父类中的方法,就要使用超类(超集)方法super(),该方法旨在调用已经被覆盖的父类的成员方法。
讨论:
有关python是如何实现继承的?
针对每一个定义的类,都会计算出一个成为方法解析顺序(MRO)的元组,其只是简单的对所有基类进行简单地线性排列。
通过上述的C类调用MRO表,我们不难看出,它将本类开始一直到object类直接所有的父类一次性从左向右逐层向上的排列了出来(先排列自己,在排列自己的父类,最后排列父类的父类,以及最后的object)
然而MRO为何如此排列,这里要涉及到一个非常令人讨厌的数学算法,C3线性化处理,这里只是总结其三个约束:(简单点说,其实就是对父类进行归并排列)
1、先检查子类,再检查父类
2、有多个父类时,按照MRO表的顺序依次查看
3、如果下一个待选的类出现了两个合法的选择,那么就从第一个父类中选取。
4、补充一点:MRO对类的排序几乎适用于任何定义的类层次结构。
来了来了,它真的来了:重点~~
有很多同学是否仔细看过上边的代码?
有关super()函数,以下重点需要各位明白:
在重写的方法中仅使用一次super()方法时,会按照MRO表从下一个类开始搜索对应的方法或属性,以此类推。 所以C中重写了父类的构造,构造中有super,所以会按照顺序去查找MRO中下一个类的方法,发现A中也有super,就会再去B中找对应的方法(同名方法是__init__),所以找到B的构造,可是B中又有super,就会再去MRO中B的下一个类(Base)中找对应的方法(Base的__init__()方法),所以会先打印“Base.__init__”,打印完后又因为B的__init__中还有打印“B.__init__”,所以接着打印‘B.__init__’,又因为打印完后A中还有打印“A.__init__”,所以再打印“A.__init__”,最后打印“C.__init__”。这样就可以遍历MRO整张表中所有的对应的__init__()方法,并且让每个方法只会被调用一次。
为了更好的记忆:当所有重写的方法中只使用了一次super函数时,会从最上层的类依次调用其指定的方法即可以理解为(object-Base-B-A-C)。
所以,输出结果为:
甚至于如下情况更为耐人寻味,仔细品一品:
值的一提的是:AB均没有显式的继承的父类,为何结果为打印‘AB’呢?这里就要理解MRO的含义了哦!
python的类和对象中的super函数的问题
问题一
因为在B类中调用了super方法,所以没有执行完B类就去执行C类的程序
super方法在多重继承程序中的调用顺序,采用的是C3算法(在python3中)。
C3算法的规则如下
①.从底层开始,选择入边为零的点。
②.从左到右。
③深度探索。但受限于②规则。
每一个类都可以用mro函数查看自己的继承顺序(MRO全称Method Resolution Order,就是用来定义继承方法的调用顺序)
对于你的程序
分析
①规则。得到D类,去掉D类以后,入边为零的是B类和C类
②规则。选择B类,去掉B类后,入边为零的只有C类。结论是D–B–C–A。
在d=D()语句前加print(D.mro()),就可以打印出D类的继承顺序
[class '__main__.D', class '__main__.B', class '__main__.C', class '__main__.A', class 'object']
问题二
python3的继承不同于普通的继承,super函数已经考虑到了重复继承的问题,所以对于A类只访问一次
python 关于super的疑问
MRO(Method resolution order)是python用来解析方法调用顺序的,mro中记录了一个类的所有基类的类类型序列,super不是简单地调用基类的方法,而是按照MRO中的顺序来调用类的方法。
使用super()时,应该在所有类中使用,否则就可能发生有的类构造函数没有调用的情况。
#!/usr/bin/python
# -*- coding: utf-8 -*-
class A(object):
def __init__(self):
print 'A __init__'
super(A, self).__init__()
print 'leave A'
class C(object):
def __init__(self):
print 'C __init__'
super(C, self).__init__()
print 'leave C'
class B(A,C):
def __init__(self):
print 'B __init__'
super(B, self).__init__()
print 'leave B'
class D(B):
def __init__(self):
print 'D __init__'
super(D, self).__init__()
print 'leave D'
if __name__ == '__main__':
D()
输出为:
D __init__
B __init__
A __init__
C __init__
leave C
leave A
leave B
leave D
又来求助了,大神求解答 python类继承的问题
老式类就是经典类,不是继承自object类.在多继承时采用深度优先遍历父类.
新式类就是基类继承自object类 class xxx(object).多继承时采用一种新的C3 算法来遍历父类.
实例如下:
class GrandFather(object):
def speak(self):
print "speak: I am grandfather"
class Father(GrandFather):
def eat(self):
pass
class Mother(GrandFather):
def speak(self):
print "speak: I am mother"
class Son(Father, Mother):
def eat(self):
pass
#GrandFather继承object就为"新式类",去掉就为"旧式类"
son = Son()
son.speak()
新式类的打印结果如下:
1
speak: I am mother
旧式类的打印结果如下:
1
speak: I am GrandFather
由此我们可以看出新式类的搜索过程为:Son--Father--Mother,而旧式类的搜索过程为:Son--Father--GrandFather
我们可以看出旧式类和我们预期的继承不太一样。
老式类就是经典类,不是继承自object类.在多继承时采用深度优先遍历父类.
新式类就是基类继承自object类 class xxx(object).多继承时采用一种新的C3 算法来遍历父类.
为什么采用C3算法呢?
C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。
为了解释C3算法,我们引入了mro(mro即 method resolution order (方法解释顺序),主要用于在多继承时判断属性的路径(来自于哪个类))。
我们可以通过class.mro()来查看python类的mro
C3算法
判断mro要先确定一个线性序列,然后查找路径由由序列中类的顺序决定。所以C3算法就是生成一个线性序列。
如果继承至一个基类:
class B(A)
这时B的mro序列为[B,A]
如果继承至多个基类
class B(A1,A2,A3 ...)
这时B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
merge操作就是C3算法的核心。
遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。
merge操作后的序列,继续执行merge操作,直到merge操作的序列为空。
如果merge操作的序列无法为空,则说明不合法。
例子:
class A(O):pass
class B(O):pass
class C(O):pass
class E(A,B):pass
class F(B,C):pass
class G(E,F):pass
A、B、C都继承至一个基类,所以mro序列依次为[A,O]、[B,O]、[C,O]
mro(E) = [E] + merge(mro(A), mro(B), [A,B])
= [E] + merge([A,O], [B,O], [A,B])
执行merge操作的序列为[A,O]、[B,O]、[A,B]
A是序列[A,O]中的第一个元素,在序列[B,O]中不出现,在序列[A,B]中也是第一个元素,所以从执行merge操作的序列([A,O]、[B,O]、[A,B])中删除A,合并到当前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])
再执行merge操作,O是序列[O]中的第一个元素,但O在序列[B,O]中出现并且不是其中第一个元素。继续查看[B,O]的第一个元素B,B满足条件,所以从执行merge操作的序列中删除B,合并到[E, A]中。
mro(E) = [E,A,B] + merge([O], [O])
= [E,A,B,O]
新闻名称:pythonmro函数 python chrom
当前链接:http://scyanting.com/article/hepsps.html