继承

定义:继承就是让类和类产生父子关系,这样,子类就可拥有父类的属性和方法。当然私有属性和私有方法是不能被继承的,类外面增加的对象属性也不能被继承

父类和子类:

  • 父类:被继承的类,称为父类,也叫作基类
  • 子类:继承其他类的类,称为子类,也叫作派生类

目的:提高代码的复用率

格式:

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__)

python中基类的同名方法可以调用吗_覆写


可以看到,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中基类的同名方法可以调用吗_子类_02

继承原理

对于定义的每一个类,在python内部会计算出一个方法解析顺序(mro)表,这个表从左到右的顺序,就是我们继承的顺序,继承过程遵守的准则:

  1. 子类先于父类被检查
  2. 多个父类根据他们在列表中的顺序被检查
  3. 如果下一个类存在两个或两个以上的选择,选择最左边的父类
  4. 查看一个类继承的顺序: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())

python中基类的同名方法可以调用吗_父类_03



多重继承

深度优先

对于旧式类,不继承object,执行深度优先:

python中基类的同名方法可以调用吗_父类_04


在多重继承中,如果继承的类只有一层,那么将执行深度继承:

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()

python中基类的同名方法可以调用吗_子类_05

广度优先

对于新式类,执行广度优先

python中基类的同名方法可以调用吗_python_06

如果继承的类大于一层,执行广度继承:

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())

python中基类的同名方法可以调用吗_覆写_07



-------------------------------------------------------------------------------------------------------------

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())

python中基类的同名方法可以调用吗_子类_08


python中基类的同名方法可以调用吗_python中基类的同名方法可以调用吗_09

继承过程要注意的

在覆写一个方法时,我们有两种方法来写,在这里以__init__为例:

  1. 一种是父类名.父类方法名(self,属性1,属性2,属性3)
  2. 一种是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")

python中基类的同名方法可以调用吗_python_10