python-类的继承和多态-继承父类方法和属性的多种方法-继承多个类,继承顺序的研究

一、Reference

Python interview - override & overload_加藤蜀黍的博客-CSDN博客

Python:类的继承,调用父类的属性和方法基础详解_奥卡姆的剃刀的博客-CSDN博客_python调用父类方法

二、继承父类方法和属性的4种方法

2.1 直接继承不加改变

此时,由于不会覆盖父类的属性和方法,所以不用调用父类来进一步继承。

class Father():
    def __init__(self):
        self.a = 'aaa'

    def action(self):
        print('调用父类的方法')


class Son(Father):
    pass


son = Son()  # 子类Son 继承父类Father的所有属性和方法
son.action()  # 调用父类方法
print(son.a)  # 调用父类属性

# 输出结果如下:
# 调用父类的方法
# aaa

2.2 覆盖继承之super()函数

覆盖继承什么意思呢?就是需要在父类的基础上修改、添加属性。

这时候,由于会重新执行一遍def xxx,因此会覆盖掉父类的方法,为了进一步保留覆盖掉的属性或方法,可以使用super()函数来进一步继承。

注意:super()是调用MRO顺序中上一父类,如果想要详细了解MRO,继续看本文的第三部分。

class Father():
    def action(self):
        print('调用父类的方法')
 
class Son(Father):
    def action(self):
        super().action()
son=Son()
son.action() 

# 输出结果如下:
# 调用父类的方法

 python3.x支持直接用super(),但是对于python2.x,必须用super(subclass_name, self)。

当然python3.x中,使用super(subclass_name, self)也没出错!

class Father():
    def action(self):
        print('调用父类的方法')
 
class Son(Father):
    def action(self):
        super(Son, self).action()
son=Son()
son.action() 

# 输出结果如下:
# 调用父类的方法

 那如果想要往父类定义的方法中传入参数怎么办?在方法函数中传入参数,不用写self。在super中,既可以传也可不传。

class Father():
    def action(self, name='ghost'):
        print('调用父类的方法', name)


class Son(Father):
    def action(self):
        super().action('people')
        # 上面这行等效于下面这行代码
        # super(Son, self).action('people')


son = Son()
son.action()

# 输出结果如下:
# 调用父类的方法 people

2.3 覆盖继承之父类调用法

在子类中直接调用父类方法时,需要传入self以及其他相关参数。

class Father():
    def action(self, name='ghost'):
        print('调用父类的方法', name)
 
class Son(Father):
    def action(self):
        Father.action(self, 'people')
son=Son()
son.action() 

# 输出结果如下:
# 调用父类的方法 people

2.4 私有属性的继承方法

对于单下划线的弱私有属性,可以直接按正常的普通属性调用(虽然调用的时候和普通属性无异,但是pycharm仍会有所警告,毕竟这样是不符合语法规范的写法);对于双下划线的强私有属性,需要在强私有属性前加【单下划线+类名】。

class F(object):
    _pro0 = 6
    __pro1 = 12

    def __init__(self):
        self._pro2 = 24
        self.__pro3 = 48


class f(F):
    def __init__(self):
        super(f, self).__init__()

    def speak(self):
        print(self._pro0)
        print(self._F__pro1)
        print(self._pro2)
        print(self._F__pro3)

instance1 = f()
instance1.speak()

# 输出结果为:
# 6
# 12
# 24
# 48

三、继承多个类时,继承顺序的研究

下面主要是讲解python3.x的MRO机制——C3线性算法。因为未来python2.x肯定越来越少人会使用了,讲了没用。

参考链接

C3线性优化算法_cf313995的博客-CSDN博客_c3线性算法

Python的方法解析顺序(MRO)[转] - morra - 博客园

利用两个较为复杂的多继承范例来辅助各位读者理解C3线性算法。

3.1 C3线性算法基本规律

(1)预定义 

  • 每一个列表的头元素H是指第1个元素,尾元素群包括第2至最后一个元素。
  • 检查工作是指将头元素H与其他列表尾元素群中的元素进行比对,如果尾元素群中存在就可输出,不存在就继续遍历下一个列表。

 (2)具体步骤

步骤一:检查第一个列表的头元素H。

步骤二:若第一个列表头元素H未出现在其它列表尾元素群,则将其输出,并将其从所有列表中删除,然后回到步骤一,再去检查新列表组合中的第一个列表的头元素H在其他列表尾元素群中是否存在;否则,检查下一个列表的头元素H,看其他列表尾元素群中有无H,如果还是没找到就再找下一个列表的头元素H。

(3)注意

  1. 每一次成功检查到当前列表头元素中不是其他列表尾元素时,在去除头元素后要回到第一个列表,但是如果一直没有不断重复步骤一和二,直至列表为空。
  2. 如果最后能把merge里面的列表清空,则说明多继承关系正常,可以得到一个符合C3线性关系的继承顺序。
  3. 如果最后不能再找出可以清除的元素,说明存在异常,需要重新定义类的继承关系。

3.2 范例一

在这里插入图片描述

先计算底层类的MRO,再计算浅层类;O代表object
L[O]=O
L(C)=C+merge[L[O],[O]]=C,O
L(A)=A+merge[L[O],[O]]=A,O
L(B)=A+merge[L[O],[O]]=B,O
L(D)=A+merge[L[O],[O]]=D,O
L(E)=A+merge[L[O],[O]]=E,O

L(K1)=K1+merge(L[C],L[A],L[B],[C,A,B])
=K1+merge([C,O],[A,O],[B,O],[C,A,B])
=[K1,C]+merge([O],[A,O],[B,O],[A,B])
=[K1,C,A]+merge([O],[O],[B,O],[B])
=[K1,C,A,B]+merge([O],[O],[O])
=[K1,C,A,B,O]

同理可得:
L(K3)=[K3,A,D,O]
L(K2)=[K2,B,D,E,O]

L(Z)=Z+merge(L[K1],L[K2],L[K3],[K1,K2,K3])
=Z+merge(L[K1,C, A,B,O],L[K3,A,D,O],L[K2,B,D,E,O],[K1,K3,K2])
=[Z,K1]+merge(L[C, A,B,O],L[K3,A,D,O],L[K2,B,D,E,O],[K3,K2])
=[Z,K1,C]+merge(L[ A,B,O],L[K3,A,D,O],L[K2,B,D,E,O],[K3,K2])
=[Z,K1,C,K3]+merge(L[ A,B,O],L[A,D,O],L[K2,B,D,E,O],[K2])
=[Z,K1,C,K3,A]+merge(L[ B,O],L[D,O],L[K2,B,D,E,O],[K2])
=[Z,K1,C,K3,A,K2]+merge(L[ B,O],L[D,O],L[B,D,E,O])
=[Z,K1,C,K3,A,K2,B]+merge(L[O],L[D,O],L[D,E,O])
=[Z,K1,C,K3,A,K2,B,D]+merge(L[O],L[O],L[E,O])
=[Z,K1,C,K3,A,K2,B,D,E]+merge(L[O],L[O],L[O])
=[Z,K1,C,K3,A,K2,B,D,E,O]

所以类Z的查找顺序为:Z,K1,C,K3,A,K2,B,D,E,O

程序验证

class A(object):pass
class B(object):pass
class C(object):pass
class D(object):pass
class E(object):pass
class K1(C, A, B):pass
class K2(B, D, E):pass
class K3(A, D):pass
class Z(K1, K3, K2):pass


for i in Z.__mro__:
    print(i.__name__, end='')


# 输出结果为ZK1CK3AK2BDEobject

3.3 范例二

L[object] = [object]
L[D] = [D, object]
L[E] = [E, object]
L[F] = [F, object]
L[B] = [B, D, E, object]
L[C] = [C, D, F, object]
L[A] = [A] + merge(L[B], L[C], [B], [C])
     = [A] + merge([B, D, E, object], [C, D, F, object], [B], [C])
     = [A, B] + merge([D, E, object], [C, D, F, object], [C])
     = [A, B, C] + merge([D, E, object], [D, F, object])
     = [A, B, C, D] + merge([E, object], [F, object])
     = [A, B, C, D, E] + merge([object], [F, object])
     = [A, B, C, D, E, F] + merge([object], [object])
     = [A, B, C, D, E, F, object]

代码验证:

class D(object): pass
class E(object): pass
class F(object): pass
class B(D, E): pass
class C(D, F): pass
class A(B, C): pass


for i in A.__mro__:
    print(i.__name__, end='')
    
# 输出结果为:ABCDEFobject
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值