文章目录
一、继承
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)
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