继承
0.了解继承
Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法。
在Python中,所有类默认继承object类,object类是顶级类(基类),其他子类叫做派生类。
继承的好处:提高代码的重用率,节省了代码量。
继承的特点:
- 子类默认拥有父类的所有属性和方法 //不继承给子类的属性和方法需要添加私有权限
- 子类能重写父类同名方法和属性
- 子类能调用父类同名属性和属性 //super()快速调用父类方法
1. 经典类和新式类
经典类:不由任意内置类型派生出的类(Python2.0版本默认是经典类)
class 类名:
code
新式类(Python3.0默认)
class 类名(object):
code
2. 继承
# 父类A
class A(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
# 子类B
class B(A):
pass
result =B()
result.info_print() #1
3. 单继承
煎饼果子师父把果子技术传授给徒弟。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(Master):
pass
result =Prentice()
print(result.skill) # [煎饼果子配方]
result.make_cake() # 运用[煎饼果子配方]制作果子
4. 多继承
当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
徒弟从师父和学校学果子技术。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice1(Master,School):
pass
class Prentice2(School,Master):
pass
result1 =Prentice1()
print(result1.skill) # [煎饼果子配方]
result1.make_cake() # 运用[煎饼果子配方]制作果子
result2 =Prentice2()
print(result2.skill) # [黑马果子]
result2.make_cake() # 运用[黑马果子]制作果子
5. 子类重写父类同名属性和方法
子类重写父类同名属性和方法后,子类和父类拥有同名属性和方法,子类创建对象调用属性和方法的时候,调用到的是子类里面的同名属性和方法。
徒弟在掌握师父和学校果子技术后,自创一果子技术。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(School,Master):
def __init__(self):
self.skill = '[自创果子术]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
result = Prentice()
print(result.skill) # [自创果子术]
result.make_cake() # 运用[自创果子术]制作果子
6. mro顺序
类名.__mro__
mro:方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序。
用来看类的层级关系
mro采用C3 线性化算法,遵循以下规则:
● 子类永远在父类前面
● 如果有多个父类,会根据它们在列表中的顺序被检查
● 如果对下一个类存在两个合法的选择,选择第一个父类
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(School,Master):
def __init__(self):
self.skill = '[自创果子术]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
result = Prentice()
print(result.skill) # [自创果子术]
result.make_cake() # 运用[自创果子术]制作果子
print(Prentice.__mro__)
类继承的顺序:
(<class 'main.Prentice'>, <class 'main.School'>, <class 'main.Master'>, <class 'object'>)
7. 子类调用父类的同名方法和属性
顾客也希望吃徒弟用师父和学校技术做的果子。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(School,Master):
def __init__(self):
self.skill = '[自创果子术]'
def make_cake(self):
# 先调用自己子类的初始化,if先调用父类的属性和方法,父类会覆盖子类属性。
self.__init__()
print(f'运用{self.skill}制作果子')
# 调用父类方法
# 为保证调用到的也是父类的属性,必须在调用前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
result = Prentice()
print(result.skill) # [自创果子术]
result.make_cake() # 运用[自创果子术]制作果子
result.make_master_cake() # 运用[煎饼果子配方]制作果子
result.make_school_cake() # 运用[黑马果子]制作果子
8. 多层继承
师父把某果子技能给徒弟,徒弟把所有果子技能给徒孙。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(School,Master):
def __init__(self):
self.skill = '[自创果子术]'
def make_cake(self):
self.__init__()
print(f'运用{self.skill}制作果子')
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
result =Tusun()
result.make_cake() # 运用[自创果子术]制作果子
result.make_master_cake() # 运用[煎饼果子配方]制作果子
result.make_school_cake() # 运用[黑马果子]制作果子
9. super()调用父类方法
使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 法二
super(Master,self).__init__()
super(Master,self).make_cake()
# 学校类School
class School(object):
def __init__(self):
self.skill='[黑马果子]'
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 徒弟类Prentice
class Prentice(Master,School):
def __init__(self):
self.skill = '[自创果子术]'
def make_cake(self):
self.__init__()
print(f'运用{self.skill}制作果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 一次性调用父类的同名属性和方法
def make_old_cake(self):
'''
# 法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
Master.__init__(self)
Master.make_cake(self)
School.__init__(self)
School.make_cake(self)
'''
# 法二:super()
super().__init__()
super().make_cake()
'''
也可写作:super(当前类名,self).函数() //不过麻烦
super(Prentice,self).__init__()
super(Prentice,self).make_cake()
'''
result=Prentice()
result.make_old_cake()
'''
运用[煎饼果子配方]制作果子
运用[黑马果子]制作果子
'''
10. 定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
设置私有权限的方法:在属性名和方法前面加上两个下划线__。
师父授之以渔,不受之以鱼。把果子技术给徒弟,不给钱。
class 类名():
def __init(self):
self.__属性名 = 值 # 私有属性
def __函数名(self):
代码
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
self.bill=0 # 公有权限
self.__money=200 # 私有属性__
# 定义私有方法__
def __info_print(self):
print(self.skill)
print(self.__money)
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 法二
super(Master,self).__init__()
super(Master,self).make_cake()
# 徒弟类Prentice
class Prentice(Master):
pass
result=Prentice()
print(result.bill) # 0
#print(result.__money)
# 'Prentice' object has no attribute '__money'
#result.__info_print()
# 'Prentice' object has no attribute '__info_print'
#即便是Master也无法获取私有属性,同样 has no attribute
11. 获取和修改私有属性值
在Python中,一般定义函数名get_××来获取私有属性,定义set_××来修改私有属性。//get、set只是习惯,非强制。
# 师父类Master
class Master(object):
def __init__(self):
self.skill ='[煎饼果子配方]'
self.__money=200 # 私有属性__
# 获取私有属性
def get_money(self):
return self.__money
#修改私有属性
def set_money(self):
self.__money= 500
# 定义私有方法__
def __info_print(self):
print(self.skill)
print(self.__money)
def make_cake(self):
print(f'运用{self.skill}制作果子')
# 法二
super(Master,self).__init__()
super(Master,self).make_cake()
# 徒弟类Prentice
class Prentice(Master):
pass
result=Prentice()
print(result.get_money()) # 200
result.set_money()
print(result.get_money()) # 500

浙公网安备 33010602011771号