继承
定义:继承就是让类和类产生父子关系,这样,子类就可拥有父类的属性和方法。当然私有属性和私有方法是不能被继承的,类外面增加的对象属性也不能被继承
父类和子类:
- 父类:被继承的类,称为父类,也叫作基类
- 子类:继承其他类的类,称为子类,也叫作派生类
目的:提高代码的复用率
格式:
class Parent(object):
pass
class Child(Parent): # 继承了Parent
pass
分类:继承按继承数目分可以分为单继承和多继承,多继承中子类可以继承多个父类
值得一提的是,在python3中,如果一个类没有继承其他类,那么这个类都默认继承了一个基类:object,这种类称为新式类。
今天主要讲继承过程中覆写类方法,子类添加对象属性以及继承原理的问题。
查看继承的类
在正式说覆写类方法之前,我可以告诉大家一个方法,来查看一个类继承的父类:
格式: 类名._bases_
class Parent(object):
pass
class Child(Parent):
pass
print(Parent.__bases__)
print(Child.__bases__)
可以看到,Child类继承了主函数下的Parent类。
方法的覆写
override method
当子类中需要使用一个与父类方法同名的类方法时,我们把重新定义这个方法的过程称为类方法的覆写。
class Parent(object):
def ticket(self):
print("成人票价300元")
class Child(Parent):
def ticket(self): # 覆写Parent中的ticket方法
print("儿童票价150元")
parent = Parent()
parent.ticket()
child = Child()
child.ticket()
继承原理
对于定义的每一个类,在python内部会计算出一个方法解析顺序(mro)表,这个表从左到右的顺序,就是我们继承的顺序,继承过程遵守的准则:
- 子类先于父类被检查
- 多个父类根据他们在列表中的顺序被检查
- 如果下一个类存在两个或两个以上的选择,选择最左边的父类
- 查看一个类继承的顺序:print( 类名.mro() ),这是python3有的方法
class Parent(object):
def ticket(self):
print("成人票价300元")
class Child(Parent):
def ticket(self): # 覆写Parent中的ticket方法
print("儿童票价150元")
print(Parent.mro())
print(Child.mro())
多重继承
深度优先
对于旧式类,不继承object,执行深度优先:
在多重继承中,如果继承的类只有一层,那么将执行深度继承:
class A:
def __init__(self):
print(1)
class B:
def __init__(self):
print(2)
class C:
def __init__(self):
print(3)
class D(A,B,C):
def __init__(self):
print(4)
super().__init__()#继承写在最前面的
d = D()
广度优先
对于新式类,执行广度优先
如果继承的类大于一层,执行广度继承:
class A(): # 3层
def __init__(self):
print("A开始")
print("A结束")
class B(A):
def __init__(self):
print("B开始")
super().__init__()
print("B结束")
class C(A):
def __init__(self):
print("C开始")
super().__init__()
print("C结束")
class D(B, C): # D 跟A没有直接继承关系,所以不要写A
def __init__(self):
print("D开始")
super().__init__()
print("D结束")
D()
print(D.mro())
-------------------------------------------------------------------------------------------------------------
class A: # 4层
def __init__(self):
print("A")
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
print("B")
class C(A):
def __init__(self):
print("C")
super().__init__()
print("C")
class D(B):
def __init__(self):
print("D")
super().__init__()
print("D")
class E(B):
def __init__(self):
print("E")
super().__init__()
print("E")
class F(C):
def __init__(self):
print("F")
super().__init__()
print("F")
class G(C):
def __init__(self):
print("G")
super().__init__()
print("G")
class H(D, E, F, G):
def __init__(self):
print("H")
super().__init__()
print("H")
h = H() # HDEBFGCAACGFBEDH
print(H.mro())
继承过程要注意的
在覆写一个方法时,我们有两种方法来写,在这里以__init__为例:
- 一种是父类名.父类方法名(self,属性1,属性2,属性3)
- 一种是super().父类方法名(属性1,属性2,属性3)
class Parent(object):
def __init__(self, name, age, house, place):
self.name = name
self.__age = age
self.house = house
self.place = place
def visit(self):
return self.name + "去" + self.place + "旅游了"
def get_age(self):
return self.__age + 1 # 通过接口返回私有属性
class Child(Parent):
def __init__(self, name, age, house, place, brother): # 父类参数写左边,子类多出来的参数写右边
super().__init__(name, age, house, place) # 父类参数必须全部写上
self.name = name # 覆写对象属性
self.brother = brother
self.age = age
def visit(self):
return self.name + "在家看弟弟" + self.brother
parent = Parent("李云龙", 43, "江南", "张家界")
print(Parent.__bases__)
p = parent.visit()
print(p)
person = Child("李梓晨", 13, "江南", "张家界", "李梓光")
print(Child.__bases__)
a = person.get_age()
b = person.visit()
print(a, b, sep="\n")