继承

继承的概念

生活中的继承,—般指的是子女继承父辈的财产。

经典类和新式类

  1. 经典类(旧式类)
    python2
class 类名:
    pass
  1. 新式类
    python3
class 类名(object):
    pass

体验继承

Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:

# 类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()

在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

单继承

故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师父要把这套技术传授给他的唯一的最得意的徒弟。
分析:徒弟是不是要继承师父的所有技术?

# 1.师傅类
class Master(object):
    def __init__(self):
        self.kongfu = '蟹黄堡牌煎饼果子秘方'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

# 2.徒弟类
class Prentice(Master):
    pass

# 3.创建对象
zhangshan = Prentice()

# 4.访问实例属性
print(zhangshan.kongfu)
zhangshan.make_cake()

'''
蟹黄堡牌煎饼果子秘方
运用蟹黄堡牌煎饼果子秘方制作煎饼果子
'''

多继承

故事推进: zhangsan是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,在百度搜索到老王煎饼铺,报班学习煎饼果子技术。

所谓多继承意思就是一个类同时继承了多个父类。

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

zhangshan = Prentice()
print(zhangshan.kongfu)
zhangshan.make_cake()

'''
老王牌煎饼果子秘方
运用老王牌煎饼果子秘方制作煎饼果子
'''

注意: 当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法**。

子类重写父类同名方法和属性

故事: zhangsan掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。

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}制作煎饼果子')

zhangshan = Prentice()
print(zhangshan.kongfu)
zhangshan.make_cake()

'''
独创煎饼果子配方
运用独创煎饼果子配方制作煎饼果子
'''

注意:如果子类和父类拥有同名属性和方法,子类创建对象调用属性和方法的时候,调用到的是子类里面的同名属性和方法。

MRO继承顺序

MRO(Method Resolution Order)是用于确定多继承类中方法解析顺序的算法。当一个类继承自多个父类时,Python 使用MRO来决定方法查找的顺序,以确保在方法被调用时能够正确地找到继承链中的对应方法。

MRO使用C3线性化算法来生成一个有序的方法解析列表。具体来说,对于一个类及其父类的继承关系,MRO会按照如下规则生成方法解析顺。

  1. 首先,子类的MRO列表中会先包含类本身。
  2. 然后,MRO列表会按照类的继承顺序依次包含每个直接父类。如果一个类继承自多个父类,那么父类在MRO列表中出现的顺序将会保持从左到右的继承顺序。
  3. 接着,对于每个直接父类,MRO会按照同样的规则递归地包含其所有基类。在递归过程中,如果多个类共享相同的基类,那么该基类只会在MRO列表中出现一次,并且会保持从左到右的继承顺
---omit---
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__()  # 这里不需要self形参 
        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)

if __name__ == '__main__':
    zhangshan = Prentice()

多层继承

故事:N年后, zhangsan老了,想要把所有技术传承给自己的徒弟。

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

if __name__ == '__main__':
    lisi = Tusun()
    lisi.make_cake()
    lisi.make_master_cake()
    lisi.make_school_cake()


'''
运用独创煎饼果子配方制作煎饼果子
运用蟹黄堡牌煎饼果子秘方制作煎饼果子
运用老王牌煎饼果子秘方制作煎饼果子
'''

super()调用父类方法

比如有这样一个需求,zhangsan需要同时调用父类master和school的方法

写法有两种:

  1. super(当前类名, self).函数()
  2. 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 带参数写法
        # super(School, self).__init__()
        # super(School, self).make_cake()

        # super 无参数写法
        super().__init__()
        super().make_cake()

class Prentice(School):
    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)

    def make_old_cake(self):
        # 方法一:如果父类名修改,这里也要修改;代码量大,冗余
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)

        # 方法二:supper()
        # super(当前类名, self).函数()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()
        # 这种方法当自己类类名变化时,也要修改,并且较第一种代码数量没有减少

        # super().函数()  无参数
        super().__init__()
        super().make_cake()
        

# 徒孙类
class Tusun(Prentice):
    pass

if __name__ == '__main__':
    lisi = Tusun()
    lisi.make_old_cake()

'''
运用老王牌煎饼果子秘方制作煎饼果子
运用蟹黄堡牌煎饼果子秘方制作煎饼果子
'''

私有权限

定义私有属性和方法

在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
故事: zhangsan把技术传承给徒弟的同时,不想把自己的钱(2000000个亿)继承给徒弟,这个时候就要为钱这个实例属性设置私有权限。

设置私有权限的方法: 在属性名和方法名前面加上两个下划线__

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}制作煎饼果子')

class Prentice(School):
    def __init__(self):
        self.kongfu = '独创煎饼果子配方'
        self.__money = 20000

    def make_cake(self):
        self.__init__()  
        print(f'运用{self.kongfu}制作煎饼果子')

# 徒孙类
class Tusun(Prentice):
    pass

if __name__ == '__main__':
    lisi = Tusun()
    print(lisi.__money)

'''
AttributeError                            Traceback (most recent call last)
Cell In[25], line 30
     28 if __name__ == '__main__':
     29     lisi = Tusun()
---> 30     print(lisi.__money)

AttributeError: 'Tusun' object has no attribute '__money'
'''

获取和修改私有属性值

在Python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。

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}制作煎饼果子')

class Prentice(School):
    def __init__(self):
        self.kongfu = '独创煎饼果子配方'
        self.__money = 20000

    # 获取私有属性值
    def get_money(self):
        return self.__money
    
    # 修改私有属性值
    def set_money(self, money):
        self.__money = money

    def make_cake(self):
        self.__init__()  
        print(f'运用{self.kongfu}制作煎饼果子')

# 徒孙类
class Tusun(Prentice):
    pass

if __name__ == '__main__':
    lisi = Tusun()
    print(lisi.get_money())

    lisi.set_money(500)
    print(lisi.get_money())

'''
20000
500
'''

`

posted @ 2023-07-26 00:24  风有遗霜  阅读(32)  评论(0)    收藏  举报