• 『无为则无心』Python面向对象 — 54、重写和super()函数


    1、重写

    在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个特点我们成为叫做方法的重写(覆盖:override)。

    故事继续:徒弟掌握了师父和学院派技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。

    python
    # 1.创建师父类,属性和方法
    class Master(object):
        def __init__(self):
            self.kongfu = '[古法煎饼果子配方]'
    
        def make_cake(self):
            print(f'运用{self.kongfu}制作煎饼果子')
    
    
    # 2.创建学院派类 属性和方法
    class School(object):
        def __init__(self):
            self.kongfu = '[学院派煎饼果子配方]'
    
        def make_cake(self):
            print(f'运用{self.kongfu}制作煎饼果子')
    
    
    # 3.独创配方
    class Prentice(School, Master):
        def __init__(self):
            self.kongfu = '[独创煎饼果子配方]'
    
        def make_cake(self):
            print(f'运用{self.kongfu}制作煎饼果子')
    
    
    # 4. 用徒弟类创建对象,调用实例属性和方法
    tudi = Prentice()
    print(tudi.kongfu)
    tudi.make_cake()
    """
    输出结果
    [独创煎饼果子配方]
    运用[独创煎饼果子配方]制作煎饼果子
    """

    结论:子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。

    拓展:

    当我们调用一个对象的方法时,会优先去当前对象中寻找是否具有该方法,如果有则直接调用。

    如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法。

    如果没有,则去父类的父类中寻找,以此类推,直到找到object,如果依然没有找到,则报错。

    2、super()函数

    在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super() 函数来实现。

    实际需求就是:子类调用父类的同名方法和属性。

    方式一

    故事继续:虽然自己独创的煎饼果子配方非常受欢迎,但是还是有顾客都希望也能吃到古法和学院技术的煎饼果子。

    python
    # 1.创建师父类,属性和方法
    class Master(object):
        def __init__(self):
            self.kongfu = '[古法煎饼果子配方]'
    
        def make_cake(self):
            print(f'运用{self.kongfu}制作煎饼果子')
    
    
    # 2. 定义徒弟类,继承师父类
    #   添加和父类同名的属性和方法
    class Prentice(Master):
        def __init__(self):
            self.kongfu = '[独创煎饼果子配方]'
    
        # 子类的make_cake(self)方法
        def make_cake(self):
            """
            加自己的初始化的原因:
            如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,
            如果不加这个自己的初始化,
            kongfu属性值是上一次调用的init内的kongfu属性值
    
            执行方式如下:
            # 创建一个子类对象
            tudi = Prentice()
            # 调用执行父类中的make_cake()方法
            tudi.make_master_cake()
            # 调用子类中的make_cake()
            tudi.make_cake()
            就能看到劫、结果。
    
            所以在调用属性前,先调用自己子类的初始化,要记住。
            """
            self.__init__()
            print(f'运用{self.kongfu}制作煎饼果子')
    
        # 调用父类的make_cake()方法
        # 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
        # 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        def make_master_cake(self):
            # 父类类名.函数()
            # 再次调用初始化的原因:这里想要调用父类的同名方法和属性,
            # 属性在init初始化位置,所以需要再次调用init
            Master.__init__(self)
            Master.make_cake(self)
    
    
    # 3 . 用徒弟类创建对象,调用实例属性和方法
    # 创建一个子类对象
    tudi = Prentice()
    
    # 调用执行父类中的make_cake()方法
    tudi.make_master_cake()
    
    # 调用子类中的make_cake()
    tudi.make_cake()
    
    """
    输出结果:
    运用[古法煎饼果子配方]制作煎饼果子
    运用[独创煎饼果子配方]制作煎饼果子
    """

    方式一:make_master_cake()方法中的代码冗余;父类类名如果变化,那么在子类中会涉及多处修改,另外,Python是允许多继承的语言,如上所示的方法在多继承时就需要重复写多次,显得累赘。为了解决这些问题,Python提供了super()函数解决此问题。

    方式二

    使用super()函数调用父类中的同名方法。

    python
    # 1.创建师父类,属性和方法
    class Master(object):
        def __init__(self):
            self.kongfu = '[古法煎饼果子配方]'
    
        def make_cake(self):
            print(f'运用{self.kongfu}制作煎饼果子')
    
    
    # 2. 定义徒弟类,继承师父类
    #   添加和父类同名的属性和方法
    class Prentice(Master):
        def __init__(self):
            self.kongfu = '[独创煎饼果子配方]'
    
        # 子类的make_cake(self)方法
        def make_cake(self):
            self.__init__()
            print(f'运用{self.kongfu}制作煎饼果子')
    
        # 调用父类的make_cake()方法
        # 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
        # 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        def make_master_cake(self):
            # 方法二: super()
            # super函数需要传递的参数:(当前类名, self)前边是类名,后边是对象
            # 方式一: super(当前类名, self).函数()
            # super(Prentice, self).__init__()
            # super(Prentice, self).make_cake()
    
            # 方式二; 简便方法,使用super().函数(),参数可省略。
            super().__init__()
            super().make_cake()
    
    
    # 3 . 用徒弟类创建对象,调用实例属性和方法
    # 创建一个子类对象
    tudi = Prentice()
    
    # 调用执行父类中的make_cake()方法
    tudi.make_master_cake()
    
    # 调用子类中的make_cake()
    tudi.make_cake()
    
    """
    输出结果:
    运用[古法煎饼果子配方]制作煎饼果子
    运用[独创煎饼果子配方]制作煎饼果子
    """

    注意:使用super()函数可以自动查找父类。调用顺序遵循 __mro__ 类属性的顺序。比较适合单继承使用。

    __mro__内置类属性说明

    在Python中快速查看一个类的所继承的父类,以及父类的层级关系的方法,返回的结果是一个元组。

    python
    # 如上边示例
    # 语法:类名.__mro__
    print(Prentice.__mro__)
    
    """
    输出结果:
    (, , )
    
    可以看到返回的是一个元组,
    `super()`函数在这个元组的类中,依次查找相关属性或方法。
    """

    __EOF__

  • 本文作者: 繁华似锦的博客
  • 本文链接: https://www.cnblogs.com/liuyuelinfighting/p/15930873.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【ijkplayer】编译 Android 版本的 ijkplayer ⑦ ( 使用 AS 打开源码 | 重新设置 AGP 和 Gradle 版本号 | 设置依赖仓库 | 设置依赖 | 编译运行 )
    JavaSE_第7章 面向对象基础(下)
    Go :复制预声明功能的半穷举测试(附完整源码)
    三菱电子推出16W GaN PA,用于大规模MIMO
    SpringMVC学习篇(六)
    css中的单位
    回溯算法 | 排列问题 | leecode刷题笔记
    计算机技术的未来趋势,猿代码为先进计算行业持续造血
    Flask与PyQt结合使用时候,阻塞,界面卡死
    nacos安装配置和单机部署教程
  • 原文地址:https://www.cnblogs.com/liuyuelinfighting/p/15930873.html