继承
一、继承的概念
在生活中,继承就是后代继承先代的财产。
在Python中,面向对象编程思想的继承,表示一个子类可以继承多个父类,
当子类继承父之后,那么子类就拥有父类的所有属性和方法
继承的作用:将冗余代码删除,增加代码复用性。
class A(object):
def __init__(self):
self.id = 1
def a_method(self):
print(self.id)
class B(A):
pass
b = B()
print(b.id)
b.a_method()
二、单继承
场景:一名司机有爷爷,他爷爷会开摩托车,爷爷有驾照C
class GrandPa(object):
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Driver(GrandPa):
pass
d = Driver()
print(d.id)
d.drive()
一个子类只有一个父类。
三、多继承
场景:这个名司机的父亲会开汽车,它有驾照B,这名司机想要继承父亲的驾照。
class GrandPa(object): # 爷爷类
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Father(object): # 父亲类
def __init__(self):
self.id = 'B'
def drive(self):
print(f'拿着{self.id}照去开汽车')
class Driver(Father, GrandPa): # 司机
pass
d = Driver()
print(Driver.__mro__) # 查看子类多继承父类的顺序
print(d.id) # B
d.drive() # 拿着B照去开汽车
''' 输出结果
(<class '__main__.Driver'>, <class '__main__.Father'>, <class '__main__.GrandPa'>, <class 'object'>)
B
拿着B照去开汽车
'''
一个子类继承多个父类,如果多个父类存在相同的属性或者方法;
子类首先在自己的空间中查找,再在第一个父类中查找,再到第二个父类查找,直到找到。
四、子类重写父类同名方法和属性
场景:司机想自己考取A驾照,学会开公交车。
class GrandPa(object): # 爷爷类
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Father(object): # 父亲类
def __init__(self):
self.id = 'B'
def drive(self):
print(f'拿着{self.id}照去开汽车')
class Driver(Father, GrandPa): # 司机
def __init__(self): # 重写父类中__init__方法
self.id = 'A'
def drive(self): # 重写父类中drive方法
print(f'拿着{self.id}照开公交车')
d = Driver()
print(d.id) # A
d.drive() # 拿着A照开公交车
父类的功能不能满足子类的需求,子类可以在自己的空间内重写父类的方法。
重写之后,父类的同名方法不再被继承。
五、子类调用父类同名方法和属性
场景:司机除了A驾照,还想开摩托车和汽车。
class GrandPa(object): # 爷爷类
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Father(object): # 父亲类
def __init__(self): # 定义初始化方法
self.id = 'B'
def drive(self):
print(f'拿着{self.id}照去开汽车')
class Driver(Father, GrandPa): # 司机
def __init__(self): # 重写父类中__init__
self.id = 'A'
def drive(self): # 重写父类中drive方法
self.__init__() # 需要调用__ini__方法拿到A驾照
print(f'拿着{self.id}照开公交车')
# 调用Father类中方法
def drive_b(self): # 在这个实例方法中调用父类的方法
Father.__init__(self) # 调用父类的初始化方法
Father.drive(self) # 调用父类的drive方法
# 调用GrandPa类中方法
def drive_c(self):
GrandPa.__init__(self)
GrandPa.drive(self)
d = Driver()
d.drive()
d.drive_b()
d.drive_c()
d.drive()
''' 输出结果:
拿着A照开公交车
拿着B照去开汽车
拿着C照去开摩托车
拿着A照开公交车
'''
六、多层继承
场景:司机有儿子了,让子类继承司机类
class GrandPa(object): # 爷爷类
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Father(object): # 父亲类
def __init__(self): # 定义初始化方法
self.id = 'B'
def drive(self):
print(f'拿着{self.id}照去开汽车')
class Driver(Father, GrandPa): # 司机
def __init__(self): # 重写父类中__init__
self.id = 'A'
def drive(self): # 重写父类中drive方法
self.__init__() # 需要调用__ini__方法拿到A驾照
print(f'拿着{self.id}照开公交车')
# 调用Father类中方法
def drive_b(self): # 在这个实例方法中调用父类的方法
Father.__init__(self) # 调用父类的初始化方法
Father.drive(self) # 调用父类的drive方法
# 调用GrandPa类中方法
def drive_c(self):
GrandPa.__init__(self)
GrandPa.drive(self)
class Son(Driver):
pass
s = Son()
s.drive()
s.drive_b()
s.drive_c()
子类可以继承父类的父类的所有属性和方法!
七、super()调用父类方法
super()
一般使用在单继承中,super()
表示直接的父类
class GrandPa(object): # 爷爷类
def __init__(self):
self.id = 'C'
def drive(self):
print(f'拿着{self.id}照去开摩托车')
class Father(GrandPa): # 父亲类
def __init__(self): # 定义初始化方法
self.id = 'B'
def drive(self):
print(f'拿着{self.id}照去开汽车')
# def drive_c(self):
# super().__init__()
# super().drive()
class Driver(Father): # 司机
def __init__(self): # 重写父类中__init__
self.id = 'A'
def drive(self): # 重写父类中drive方法
self.__init__() # 需要调用__ini__方法拿到A驾照
print(f'拿着{self.id}照开公交车')
# 调用Father类中方法
def drive_b(self): # 在这个实例方法中调用父类的方法
# 1. 第一种调用方法:使用父类直接调用方法,方法中需要传入实例对象的引用
# Father.__init__(self) # 调用父类的初始化方法
# Father.drive(self) # 调用父类的drive方法
# 2. 第二种调用方法:super的第一个参数表示,super指向参数的父类
# super(Driver, self).__init__()
# super(Driver, self).drive()
# 3. 第三种调用方法:没有参数默认直接父类
super().__init__()
super().drive()
#调用GrandPa类中方法
def drive_c(self):
# # GrandPa.__init__(self)
# # GrandPa.drive(self)
# super().__init__()
# super().drive()
super(Father, self).__init__()
super(Father, self).drive()
d = Driver()
d.drive()
d.drive_b()
d.drive_c()
''' 输出结果:
拿着A照开公交车
拿着B照去开汽车
拿着C照去开摩托车
'''
八、私有权限
8.1 定义类的私有属性和方法
私有属性和方法的语法,使用两个下划线开头,将方法名或者属性名写在下划线之后,比如:__drive()
场景:司机有2000000元存款,儿子不争气,不想让儿子继承。使用私有属性和方法
class Driver(object):
def __init__(self):
self.id = 'A'
self.__money = 2000000
def __print_info(self): # 子类可以通过公共方法来访问私有属性
print(f'拿着{self.id}照开车')
print(f'我有存款:{self.__money}')
class Son(Driver):
pass
s = Son()
print(s.__dict__) # 打印实例对象空间所有的属性
# print(s._Driver__money) # 最好不要去访问
s._Driver__print_info()
子类无法继承父类的私有属性
在Python中,只有伪私有,原理是将私有属性改名,在私有属性之前加上
_类名
,叫做改名机制私有属性可以通过公共方法来访问
用法:如果不想让调用者直接使用这个方法或者属性,就加上私有权限。只有公共方法调用即可。
相当于在类的内部调用私有权限
8.2 获取和修改私有属性
一般来来说,在公共方法中访问私有方法或属性,建议将公共方法的名称前加上前缀:
- 获取私有属性的方法名的前缀为
get_公共方法名
- 修改私有属性的方法名的前缀:
set_公共方法名
场景:儿子争气了,考上了四川大学,父亲决定将钱留给儿子
class Driver(object):
def __init__(self):
self.__money = 2000000
def set_money(self): # 修改私有属性
self.__money = 1000000
def get_money(self):
print(self.__money)
class Son(Driver):
pass
# 实例化一个Son的对象
s = Son()
# 获取私有属性
s.get_money()
# 修改私有属性
s.set_money()
s.get_money()