面向对象-继承
1.体验继承
python面向对象的继承指多个类之间的从属关系,即子类默认及继承父类的所有属性和方法,具体如下:
#父类 class A(object): def __init__(self): self.num = 1 def info_print(self): print(self.num) #子类 class B(A): pass redult = B() redult.info_print() ''' 输出: 1 '''
在python中,所有类默认继承object类,object类是顶级类或基类,其他字类叫派生类
2.单继承
故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的煎饼果子技术。师傅要把这套技术传授给徒弟。
分析:要有两个类(师傅类、徒弟类),徒弟类继承师傅类
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master): pass tuer = Prentice() tuer.make_cake() ''' 输出: 使用独门绝技制作煎饼果子 '''
3.多继承
故事推进:tuer继承师傅的独门绝技后,还想去学校学习更多的技术
多继承:所谓多继承就是一个类同时继承多个父类
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): pass tuer = Prentice() tuer.make_cake() ''' 输出: 使用独门绝技制作煎饼果子 '''
结论:如果一个类同时继承多个父类,优先继承第一个父类的同名属性和方法
4.子类重写父类同名属性和方法
故事:徒弟掌握师傅和学校的技术后,自己潜心研究出了自己的独门秘方
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') tuer = Prentice() tuer.make_cake() ''' 输出: 使用自创秘方制作煎饼果子 '''
结论:如果子类和父类拥有同名方法和属性,子类创建对象时调用属性和方法,调用到的是子类里面的同名属性和方法
5.拓展:__mro__ 子类继承的父类以及继承顺序
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') tuer = Prentice() tuer.make_cake() print(Prentice.__mro__) ''' 输出: 使用自创秘方制作煎饼果子 使用自创秘方制作煎饼果子 (<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>) '''
6.子类调用父类的同名属性和方法
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) tuer =Prentice() tuer.make_cake() tuer.Master_make_cake() tuer.School_make_cake() ''' 输出: 使用自创秘方制作煎饼果子 使用独门绝技制作煎饼果子 使用新式秘方制作煎饼果子 '''
7.多层继承
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) class Tusun(Prentice): pass tuer =Tusun() tuer.make_cake() tuer.Master_make_cake() tuer.School_make_cake() ''' 输出: 使用自创秘方制作煎饼果子 使用独门绝技制作煎饼果子 使用新式秘方制作煎饼果子 '''
8.super()调用父类方法
带参数写法
super(当前类名,self).函数()
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(Master): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') #在这里调用super方法, 才能调用Master父类里的方法和属性 def make_cake(self): super(School, self).__init__() super(School, self).make_cake() class Prentice(School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) def make_waht_cake(self): super(Prentice, self).__init__() super(Prentice, self).make_cake() tuer =Prentice() tuer.make_waht_cake() tuer.make_cake() ''' 输出: 使用独门绝技制作煎饼果子 使用自创秘方制作煎饼果子 '''
无参数写法
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(Master): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') #在这里调用super方法, 才能调用Master父类里的方法和属性 def make_cake(self): super().__init__() super().make_cake() class Prentice(School): def __init__(self): self.mifang = '自创秘方' def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) def make_waht_cake(self): super().__init__() super().make_cake() tuer =Prentice() tuer.make_waht_cake() tuer.make_cake() ''' 输出: 使用独门绝技制作煎饼果子 使用自创秘方制作煎饼果子 '''
注意:使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用。
9.私有权限
9.1定义私有属性和方法
在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性和方法不继承给子类。
设置私有权限的方法:在属性名和方法名前面加两个_
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' self.__caichan = '2个亿' def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') def __caichan(self): print('这是私有方法') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) class Tusun(Prentice): pass tuer =Tusun() # print(tuer.caichan) #print(tuer.__caichan) # tuer.caichan() # tuer.__caichan()
四个调用都会报错,因为父类不能将私有属性和方法继承给子类
9.2获取和修改私有属性值
在python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值
class Master(object): def __init__(self): self.mifang = '独门绝技' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class School(object): def __init__(self): self.mifang = '新式秘方' def make_cake(self): print(f'使用{self.mifang}制作煎饼果子') class Prentice(Master,School): def __init__(self): self.mifang = '自创秘方' self.__caichan = 200000 def __caichan(self): print('这是私有方法') # 获取私有属性 def get_caichan(self): return self.__caichan #修改私有属性 def set_caichan(self): self.__caichan = 50000 def make_cake(self): # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用 self.__init__() print(f'使用{self.mifang}制作煎饼果子') #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装 def Master_make_cake(self): #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用 Master.__init__(self) Master.make_cake(self) def School_make_cake(self): School.__init__(self) School.make_cake(self) class Tusun(Prentice): pass tuer =Tusun() print(tuer.get_caichan()) tuer.set_caichan() print(tuer.get_caichan()) ''' 输出: 200000 50000 '''
获取和修改私有属性不一定是get_xx和set_xx,这只是工作习惯
总结
继承的特点
子类默认拥有父类的所有属性和方法
子类重写分类同名属性和方法
子类调用父类同名属性和方法
super()快速调用父类方法
私有权限
不能继承给子类的属性和方法需要添加私有权限
语法:
class 类名()
#私有属性
__属性名 = 值
#私有方法
def __函数名(self):
代码