4 子类重写父类同名方法和属性
4.1 子类重写父类同名方法和属性
子类与父类有同名的方法和属性,子类的对象调用同名方法和属性,调用的是子类的方法和属性。
大邱在继承了师傅的煎饼果子配方,以及在培训机构学习了编程技术后,经过自己的研究,最终研究出了自己的一套制作煎饼果子的方法与技术。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(object): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 徒弟类 class Prentice(School, Master): def __init__(self): self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): print(f'使用{self.kongfu}研究的新技术制作煎饼果子') # 实例化徒弟对象 prentice = Prentice() # 制作煎饼果子 prentice.make_cake()
4.2 查看子类继承的父类以及父类间的层级关系
语法:
需要查看的类的类名.__mro__
print(Prentice.__mro__)
Prentice直接继承于School与Master,间接继承于object。
5 子类调用父类的同名方法和属性
5.1 子类调用父类的同名方法和属性
虽然现在有了大邱研究出的新型制作煎饼果子的方法与技术,但是顾客们还是非常怀念古法煎饼果子,顾客询问大邱,能不能制作古法煎饼果子。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(object): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 徒弟类 class Prentice(School, Master): def __init__(self): self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): self.__init__() print(f'使用{self.kongfu}研究的新技术制作煎饼果子') # 古法煎饼果子制作 def make_master_cake(self): Master.__init__(self) Master.make_cake(self) # 实例化徒弟对象 prentice = Prentice() # 制作煎饼果子 prentice.make_cake() prentice.make_master_cake()
5.2 解释
调用父类初始化方法的原因,使用父类初始化方法重置子类对象的属性,如果不调用,子类对象的属性不会更改。
由于调用父类的初始化方法后,子类对象的属性会被修改,所以使用子类自己的属性时候,需要调用子类的初始化方法重置属性值。
6 多层继承
n年之后,大邱老了,想把自己的技术与配方传承给自己的徒弟。
大邱继承了培训机构与其师傅的技术和配方,大邱的徒弟继承了大邱的技术与配方,这就是多层继承的体现。
类名调用父类的方法,注意传递形参self。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(object): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 徒弟类 class Prentice(School, Master): def __init__(self): self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): self.__init__() print(f'使用{self.kongfu}研究的新技术制作煎饼果子') # 古法煎饼果子制作 def make_master_cake(self): Master.__init__(self) Master.make_cake(self) # 徒孙类 class TuSun(Prentice): pass # 实例化徒弟对象 xiaoqiu = TuSun() # 制作煎饼果子 # 使用从其师傅(大邱)继承的方法与配方制作 xiaoqiu.make_cake() xiaoqiu.make_master_cake()
7 super()
调用父类的方法
调用父类的方法:
(1)可以通过父类的类名调用
(2)也可以通过super()调用
Master、School、Prentice三个类的继承关系改为,School继承Master,Prentice继承School。
7.1 通过父类的类名调用
使用类名调用父类方法的形式,一次性调用父类School、Master的方法。
此方法存在的缺陷:
当父类的类名修改时,子类中调用父类方法的代码也需要进行修改;
如果调用的类多,则会使代码量庞大,造成代码冗余。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(Master): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 徒弟类 class Prentice(School): def __init__(self) -> object: self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): self.__init__() print(f'使用{self.kongfu}研究的新技术制作煎饼果子') # 一次性调用父类School、Master的方法 def make_old_cake(self): Master.__init__(self) Master.make_cake(self) School.__init__(self) School.make_cake(self) # 实例化徒弟对象 daqiu = Prentice() # 制作煎饼果子 daqiu.make_old_cake()
7.2 通过super()调用
7.2.1 方法一
语法:
super(当前类名, self).方法()
要调用父类的父类的方法,需要在父类的对应方法中调用父类的父类的方法。
该方法的缺陷:
子类的类名修改,相应的代码也要进行修改。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(Master): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 调用父类Master的方法 super(School, self).__init__() super(School, self).make_cake() # 徒弟类 class Prentice(School): def __init__(self) -> object: self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): self.__init__() print(f'使用{self.kongfu}研究的新技术制作煎饼果子') def make_old_cake(self): # 调用父类的方法 super(Prentice, self).__init__() super(Prentice, self).make_cake() # 实例化徒弟对象 daqiu = Prentice() # 制作煎饼果子 daqiu.make_old_cake()
7.2.2 方法二
super().方法()
使用super()调用父类方法,可以省略参数。
使用super()可以自动查找父类,调用顺序遵循
__mro__
类属性的顺序。比较适合单继承使用。
# 师傅类 class Master(object): def __init__(self): self.kongfu = '[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu}制作煎饼果子') # 培训机构 class School(Master): def __init__(self): self.kongfu = '[Python]' def make_cake(self): print(f'运用{self.kongfu}编写程序来制作煎饼果子') # 调用父类Master的方法 super().__init__() super().make_cake() # 徒弟类 class Prentice(School): def __init__(self) -> object: self.kongfu = '[Python、煎饼果子配方]' def make_cake(self): self.__init__() print(f'使用{self.kongfu}研究的新技术制作煎饼果子') def make_old_cake(self): # 调用父类的方法 super().__init__() super().make_cake() # 实例化徒弟对象 daqiu = Prentice() # 制作煎饼果子 daqiu.make_old_cake()
8 私有权限
8.1 定义私有属性和方法
在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
在继承关系中,父类的某些属性或方法不行继承给子类,可以将这些属性或方法设置为私有。
设置私有权限的方法:在属性名和方法名前面加上两个下划线。
默认情况下,父类的所有方法和属性都会继承给子类。
# 徒弟类 class Prentice(object): def __init__(self) -> object: self.kongfu = '[Python、煎饼果子配方]' # 私有属性 self.__money = 20000 def make_cake(self): print(f'使用{self.kongfu}研究的新技术制作煎饼果子') # 私有方法 def __info_print(self): print('私有方法') # 徒孙类 class TuSun(Prentice): pass xiaoqiu = TuSun() # print(xiaoqiu.money) xiaoqiu.__info_print()
子类不能访问父类的私有属性和方法。
8.2 获取和修改私有属性值
一般获取和修改类的私有属性值,是在类中进行获取和修改。
在Python中,一般定义函数名get_xxx
用来获取私有属性,定义set_xxx
用来修改私有属性值。
# 徒弟类 class Prentice(object): def __init__(self): self.kongfu = '[Python、煎饼果子配方]' # 私有属性 self.__money = 20000 def get_money(self): print(self.__money) def set_money(self, new_money): self.__money = new_money daqiu = Prentice() daqiu.get_money() daqiu.set_money(1000000) daqiu.get_money()