python中继承的作用以及多重继承的执行顺序

来源:互联网 发布:mac jenkins.war 启动 编辑:程序博客网 时间:2024/06/04 23:25

1.继承只会继承父类的方法,不能继承父类的变量
2.要想继承父类的变量,需要执行父类的__init__(self)方法
3.下划线开头的变量或方法,会被认为是受保护的,不能直接点出来,但如果强制打出来的话也一样能用,只是会有警告
4.静态方法中不能使用self,用@staticmethod声明这是一个静态方法
5.关于python中的getter和setter,比较规范的用法是

class Test2:    @property    def para1(self):        return self._para1    @para1.setter    def para1(self, value):        self._para1 = value    @para1.deleter    def para1(self):        del self._para1if __name__ == '__main__':    instance = Test2()    print(instance.para1)    instance.para1 = 'abc'    print(instance.para1)    del instance.para1

当然,你也可以直接用实例.变量 = xxx来修改,但这样不规范

下面进入正题,多重继承的执行顺序

class A(object):    def __init__(self):        print('A')        super(A, self).__init__()class B(object):    def __init__(self):        print('B')        super(B, self).__init__()class C(A):    def __init__(self):        print('C')        super(C, self).__init__()class D(A):    def __init__(self):        print('D')        super(D, self).__init__()class E(B,C):    def __init__(self):        print('E')        super(E, self).__init__()class F(C,B,D):    def __init__(self):        print('F')        super(F, self).__init__()class G(D,B):    def __init__(self):        print('G')        super(G, self).__init__()if __name__ == '__main__':    g = G()    print(G.mro())    f = F()    print(F.mro())

执行结果:

GDAB[<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]FCBDA[<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]

1.如果每个类都有正确的写super(X, self).__init__(),那么mro顺序的所有的类的初始化方法都会执行一遍
2.如果中途有的类没有写或错误的写了super(X, self).__init__(),那么会按mro顺序执行到执行完没写的那个类,执行结束。
3.super(X, self)不是必须点__init__(),可以点别的,但一般没有这么做的
4.类名.mro可以得到mro的顺序
5.这种写法可以实现每个类都被执行有且仅有一次。

如何推算mro顺序,这个问题比较复杂,目前我知道比较靠谱的说法是可以用一种所谓的公式计算出来

mro[G](D,B)=[G]+merge(mro[D]+mro[B]+[D,B])=[G]+merge([D]+mro[A]+[A]+[B]+[O]+[D,B])=[G]+merge([D]+[A]+[O]+[A]+[B]+[O]+[D,B])接下来是提取,提取有个原则,就是所提取的不是所有列表的表尾。如[A,B,C],A是表头,B、C是表尾。提取完成后,从所有的表头删除该数据。=[G,D]+merge([A]+[O]+[A]+[B]+[O]+[B])=[G,D,A]+merge([O]+[B]+[O]+[B])=[G,D,A,B]+merge([O]+[O])=[G,D,A,B,O]mro[F](C,B,D)=[F]+merge(mro[C]+mro[B]+mro[D]+[C,B,D])=[F]+merge([C]+[A]+[O]+[B]+[O]+[D]+[A]+[O]+[C,B,D])=[F,C]+merge([A]+[O]+[B]+[O]+[D]+[A]+[O]+[B,D])=[F,C,B]+merge([A]+[O]+[O]+[D]+[A]+[O]+[D])=[F,C,B,D]+merge([A]+[O]+[O]+[A]+[O])=[F,C,B,D,A,O]

也许你会开始怀疑提取顺序的问题,我的猜测是,首先一个原则肯定是按继承顺序来提取的。其次,先找继承的第1个类的子类,再找子类,这种顺序提取,类似于1→1.1→1.2→2→2.1→2.2。但如果发现所继承的多个类都继承了该子类,就不会执行该子类,转而执行下一个继承的类,这么做是为了避免重复执行同一个类的情况。假设1.2=2.2,被1和2都继承了,这时的执行顺序就是1→1.1→2→2.1→1.2(2.2)。

当然知不知道上面的顺序都无所谓,因为类名.mro可以告诉我们正确的顺序,不管你能不能想通,顺序就是这么个顺序,事实已经被设计者确定了。

0 0