继承

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
posted @ 2022-07-10 14:59  wakaki  阅读(40)  评论(0)    收藏  举报