Python学习笔记(十九)面向对象 - 继承
一、继承的概念
# 继承:子类继承父类的所有方法和属性
# 1. 子类
class A(object):
def __init__(self):
self.num = 2
def info_print(self):
print(self.num)
# 2. 父类
class B(A):
pass
result = B()
result.info_print() # 2
二、单继承
# 1. 师傅类:属性和方法
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 2. 徒弟类:继承师傅类
class Prentice(Master):
pass
# 3. 用徒弟类创建对象,调用实例属性和方法
daiqu = Prentice()
print(daiqu.kongfu) # [古法煎饼果子配方]
daiqu.make_cake() # 运用[古法煎饼果子配方]制作煎饼果子
三、多继承
所谓多继承就是一个类同时继承多个父类。
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School,Master):
pass
daqiu = Prentice()
print(daqiu.kongfu) # [黑马煎饼果子配方]
daqiu.make_cake() # 运用[黑马煎饼果子配方]制作煎饼果子
注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
四、子类重写父类同名属性和方法
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
daqiu = Prentice()
print(daqiu.kongfu) # [独创煎饼果子配方]
daqiu.make_cake() # 运用[独创煎饼果子配方]制作煎饼果子
结论:如果子类和父类拥有同名属性和方法,那么子类创建对象调用属性和方法的时候,调用的是子类里面的同名属性和方法。
查找某个类的继承关系:
print(Prentice.__mro__) # 得到类的继承层级关系
# (<class '__main__.Prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
五、子类调用父类同名属性和方法
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
daqiu = Prentice()
print(daqiu.kongfu) # [独创煎饼果子配方]
daqiu.make_cake() # 运用[独创煎饼果子配方]制作煎饼果子
daqiu.make_master_cake() # 运用[古法煎饼果子配方]制作煎饼果子
daqiu.make_school_cake() # 运用[黑马煎饼果子配方]制作煎饼果子
六、多层继承
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
print(xiaoqiu.kongfu) # [独创煎饼果子配方]
xiaoqiu.make_cake() # 运用[独创煎饼果子配方]制作煎饼果子
xiaoqiu.make_master_cake() # 运用[古法煎饼果子配方]制作煎饼果子
xiaoqiu.make_school_cake() # 运用[黑马煎饼果子配方]制作煎饼果子
print(Tusun.__mro__) # (<class '__main__.Tusun'>, <class '__main__.Prentice'>, <class '__main__.School'>, <class '__main__.Master'>, <class 'object'>)
七、super()调用父类方法
之前的函数类名.父类方法也可以调用父类方法,代码如下:
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 需求:一次性调用父类Master School 的方法
def make_old_cake(self):
# 方法一: 如果定义的类名修改,这里的类名也要修改,麻烦:代码量太庞大,冗余
School.__init__(self)
School.make_cake(self)
Master.__init__(self)
Master.make_cake(self)
daqiu = Prentice()
daqiu.make_old_cake()
用super()调用父类方法:
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(Master):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
super(School, self).__init__()
super(School, self).make_cake()
# 独创配方
class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 需求:一次性调用父类Master School 的方法
def make_old_cake(self):
# 方法二:super()
# 方法2.1 super(当前类名,self).函数()
super(Prentice,self).__init__()
super(Prentice,self).make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(Master):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# super(School, self).__init__()
# super(School, self).make_cake()
super().__init__()
super().make_cake()
# 独创配方
class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 需求:一次性调用父类Master School 的方法
def make_old_cake(self):
# # 方法一: 如果定义的类名修改,这里的类名也要修改,麻烦:代码量太庞大,冗余
# School.__init__(self)
# School.make_cake(self)
# Master.__init__(self)
# Master.make_cake(self)
# 方法二:super()
# # 方法2.1 super(当前类名,self).函数()
# super(Prentice,self).__init__()
# super(Prentice,self).make_cake()
# 方法2.2 无参数super().函数()
super().__init__()
super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
八、私有属性和私有方法
8.1 定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或者实例方法不继承给子类。
设置私有权限的方法:在属性名 或 方法名 前加两个下划线__
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
# 私有属性: 不能继承给子类
self.__money = 2000000
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 定义私有方法:不能继承给子类
def __info_print(self):
print('这是私有方法')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
print(xiaoqiu.money) # money 是 Prentice的私有属性,故子类没有这个属性
print(xiaoqiu.info_print) # info_print() 是Prentice的私有方法,故子类没有这个方法
8.2 获取和修改私有属性
在Python中,一般定义函数get__xx用来获取私有属性,定义set__xx用来修改私有属性值。
class Master(object):
def __init__(self):
self.kongfu ='[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School,Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
# 私有属性: 不能继承给子类
self.__money = 2000000
# 获取私有属性的值 get__xx()
def get_money(self):
return self.__money
# 修改私有属性的值 set__xx()
def set_money(self):
self.__money = 50000
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 定义私有方法:不能继承给子类
def __info_print(self):
print('这是私有方法')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
print(xiaoqiu.get_money()) # 2000000
xiaoqiu.set_money() # 修改
print(xiaoqiu.get_money()) # 50000