文章目录

  • 一、继承
  • 二、继承的方式
  • 三、多重继承


一、继承

python 中可以定义“类”来抽象出一类对象的特征和方法,所有的类都是从 “object”中继承过来的

因为类中有很多方法是重复的,所以可以把很多类都具备的共同特征或属性放到一个大类(基类)里边,python 的子类可以从基类(父类)中继承方法、属性等来直接使用。

继承以后,调用的时候其实都是跑到父类里边去调用的,object 是所有类的父类

二、继承的方式

继承的时候可以分多种:

  • 子类不需要定义 init:直接去父类找
  • 子类需要定义 init,从父类中继承 init
  • 如果父类中缺少了子类需要的需求,或者某个需要不符合子类的要求,则可以重写,就会覆盖父类的。

如何调用父类的 init:

# super() 表示父类对象,往 init 里边传参数
super().__init__(参数)
super(子类名, self).__init__(参数)

1、如果需要从父类继承 init,可以这样写:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def run(self):
        print(self.name + '正在跑步!')
class Students(Person):
    def __init__(self, name, age):
        print('-----> student 的init')
        super().__init__(name, age) # 和 super(Students).__init__(name, age) 作用相同
s = Students('Jack',18)  # 执行步骤,先调 __new__,产生新空间传给 __init__,student什么都没有,就会到其父类里边找
s.run()
>>>
-----> student 的init
Jack正在跑步!
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def run(self):
        print(self.name + '正在跑步!')
class Employee(Person):
    def eat(self):
        print(self.name + '正在吃饭!')
e = Employee('xiaohong', '18')
e.eat()
>>>
xiaohong正在吃饭!

2、需要继承父类的init,还需要添加自己新的 init:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def run(self):
        print(self.name + '正在跑步!')
class Students(Person):
    def __init__(self, name, age, sex):
        super().__init__(name, age)
        print('-----> student 的 init')
        print('sex:', sex)
s = Students('Jack',18, 'male') 
s.run()
>>>
-----> student 的 init
sex: male
Jack正在跑步!

3、重写子类 init

子类如果重新定义了 init,且没有进行 super() 继承,则会覆盖父类的 init

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def run(self):
        print(self.name + '正在跑步!')
class Employee(Person):
    def __init__(self, sex):
        self.sex = sex
        print('-----> employee 的 init')
        print('sex:', sex)

e = Employee('female')
e.run()
>>>
-----> employee 的 init
sex: female
AttributeError: 'Employee' object has no attribute 'name'

三、多重继承

父类中有相同的方法时,搜索顺序:从左至右,深度优先

class Base:
    def test(self):
        print('-------Base---------')
class A(Base):
    def test(self):
        print('AAAAAAAAAAAAAAAAAAAA')
class B(Base):
    def test(self):
        print('BBBBBBBBBBBBBBBBBBBB')
class C(Base):
    def test(self):
        print('CCCCCCCCCCCCCCCCCCCC')
class D(A, B, C):
    pass
d = D()
d.test()
import inspect
print(inspect.getmro(D))
print(D.__mro__) # 获取搜索顺序方法二
>>>
AAAAAAAAAAAAAAAAAAAA
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>)

super 指的是 MRO 表中的下一个类,多继承类是通过 MRO 的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次。

多重继承的时候,如果不使用 super(),可能会导致某个类被多次初始化,所以会使用 super来避免这种情况:

未使用 super 的效果:

class A(object):
    def __init__(self):
        print ("init A Class")

class B(A):
    def __init__(self):
        A.__init__(self)
        print("init B class")

class C(A):
    def __init__(self):
        A.__init__(self)
        print("init C class")

class D(B,C):
    def __init__(self):
        B.__init__(self)
        C.__init__(self)
        print ("init D class")

class E(A):
    def __init__(self):
        A.__init__(self)
        print('init E class')

class F(D,E):
    def __init__(self):
        D.__init__(self)
        D.__init__(self)
        print('init F class')

F = F()
>>>
init A Class
init B class
init A Class
init C class
init D class
init A Class
init B class
init A Class
init C class
init D class
init F class

使用 super 的效果:

class A(object):
    def __init__(self):
        print("init A class")

class B(A):
    def __init__(self):
        print("init B class")
        super(B, self).__init__()

class C(A):
    def __init__(self):
        print("init C class")
        super(C, self).__init__()

class D(B,C):
    def __init__(self):
        print("init D class")
        super(D, self).__init__()

class E(A):
    def __init__(self):
        print("init E class")
        super(E, self).__init__()

class F(D,E):
    def __init__(self):
        print("init F class")
        super(F, self).__init__()
F = F()
>>>
init F class
init D class
init B class
init C class
init E class
init A class