一、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线性算法。
3.1 C3线性算法基本规律
(1)预定义
- 每一个列表的头元素H是指第1个元素,尾元素群包括第2至最后一个元素。
- 检查工作是指将头元素H与其他列表尾元素群中的元素进行比对,如果尾元素群中存在就可输出,不存在就继续遍历下一个列表。
(2)具体步骤
步骤一:检查第一个列表的头元素H。
步骤二:若第一个列表头元素H未出现在其它列表尾元素群,则将其输出,并将其从所有列表中删除,然后回到步骤一,再去检查新列表组合中的第一个列表的头元素H在其他列表尾元素群中是否存在;否则,检查下一个列表的头元素H,看其他列表尾元素群中有无H,如果还是没找到就再找下一个列表的头元素H。
(3)注意
- 每一次成功检查到当前列表头元素中不是其他列表尾元素时,在去除头元素后要回到第一个列表,但是如果一直没有不断重复步骤一和二,直至列表为空。
- 如果最后能把merge里面的列表清空,则说明多继承关系正常,可以得到一个符合C3线性关系的继承顺序。
- 如果最后不能再找出可以清除的元素,说明存在异常,需要重新定义类的继承关系。
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