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

博客 动态
0 193
羽尘
羽尘 2022-02-25 15:55:47
悬赏:0 积分 收藏

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

目录
  • 1、重写
  • 2、super()函数
    • 方式一
    • 方式二
    • __mro__内置类属性说明

1、重写

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

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

# 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() 函数来实现。

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

方式一

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

# 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()函数调用父类中的同名方法。

# 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中快速查看一个类的所继承的父类,以及父类的层级关系的方法,返回的结果是一个元组。

# 如上边示例# 语法:类名.__mro__print(Prentice.__mro__)"""输出结果:(<class '__main__.Prentice'>, <class '__main__.Master'>, <class 'object'>)可以看到返回的是一个元组,`super()`函数在这个元组的类中,依次查找相关属性或方法。"""
posted @ 2022-02-25 15:02 繁华似锦Fighting 阅读(27) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员