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://hbruida.cn/article/hepsps.html