python中super()方法的详细用法

这篇具有很好参考价值的文章主要介绍了python中super()方法的详细用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、单独调用父类的方法

需求:编写一个类,然后再写一个子类进行继承,使用子类去调用父类的方法1。
使用方法1打印: 胖子老板,来包槟榔。

那么先写一个胖子老板的父类,执行一下:

class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('FatFather的name是%s' % self.name)
        print('FatFather的init调用结束')


def main():
    ff = FatFather("胖子老板的父亲")

运行一下这个胖子老板父类的构造方法__init__ 如下:

if __name__ == "__main__":
    main()

#FatFather的init开始被调用
#FatFather的name是胖子老板的父亲
#FatFather的init调用结束

好了,那么下面来写一个子类,也就是胖子老板类,继承上面的类

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')


# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        FatFather.__init__(self, name)  # 直接调用父类的构造方法
        print("%s 的爱好是 %s" % (name, self.hobby))


def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

在这上面的代码中,我使用FatFather.init(self,name)直接调用父类的方法。

运行结果如下:

if __name__ == "__main__":
    main()

#胖子老板的类被调用啦!
#FatFather的init开始被调用
#调用FatFather类的name是胖子老板
#FatFather的init调用结束
#胖子老板 的爱好是 打斗地主

二、super() 方法基本概念

除了直接使用 FatFather.init(self,name) 的方法,还可以使用super()方法来调用。

那么首先需要看super()方法的描述和语法理解一下super() 方法的使用。

1 描述

super() 函数是用于调用父类(超类)的一个方法。super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

2 语法

以下是 super() 方法的语法:

super(type[, object-or-type])

参数

  • type – 类

  • object-or-type – 类,一般是 self

Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :

Python3.x 实例:

class A:
    pass
class B(A):
    def add(self, x):
        super().add(x)
3 单继承使用super()

使用super() 方法来改写刚才胖子老板继承父类的 init 构造方法

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')


# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))


def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

从上面使用super方法的时候,因为是单继承,直接就可以使用了。

运行如下:

if __name__ == "__main__":
    main()

#胖子老板的类被调用啦!
#FatFather的init开始被调用
#调用FatFather类的name是胖子老板
#FatFather的init调用结束
#胖子老板 的爱好是 打斗地主

那么为什么说单继承直接使用就可以呢?因为super()方法如果多继承的话,会涉及到一个MRO(继承父类方法时的顺序表) 的调用排序问题。

下面可以打印一下看看单继承的MRO顺序(FatBoss.__mro__)。

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')


# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))


def main():

    print("打印FatBoss类的MRO")
    print(FatBoss.__mro__)

    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    fatboss = FatBoss("胖子老板", "打斗地主")

上面的代码使用 FatBoss.mro 可以打印出 FatBoss这个类经过 python解析器的 C3算法计算过后的继承调用顺序。

运行如下:

if __name__ == "__main__":
    main()

打印FatBoss类的MRO
(<class '__main__.FatBoss'>, <class '__main__.FatFather'>, <class 'object'>)

=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

从上面的结果 (<class ‘main.FatBoss’>, <class ‘main.FatFather’>, <class ‘object’>) 可以看出,super() 方法在 FatBoss 会直接调用父类是 FatFather ,所以单继承是没问题的。

那么如果多继承的话,会有什么问题呢?

4 多继承使用super()

假设再写一个胖子老板的女儿类,和 胖子老板的老婆类,此时女儿需要同时继承 两个类(胖子老板类,胖子老板老婆类)。

因为胖子老板有一个爱好,胖子老板的老婆需要干活干家务,那么女儿需要帮忙同时兼顾。

此时女儿就是需要继承使用这两个父类的方法了,那么该如何去写呢?
下面来看看实现代码:

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name, *args, **kwargs):
        print()
        print("=============== 开始调用 FatFather  ==================")
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
        print()
        print("=============== 结束调用 FatFather  ==================")


# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBoss  ==================")
        print('胖子老板的类被调用啦!')
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 的爱好是 %s" % (name, hobby))
        print()
        print("=============== 结束调用 FatBoss  =================")

#学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441
# 胖子老板的老婆类 继承 FatFather类
class FatBossWife(FatFather):
    def __init__(self, name, housework, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBossWife  ===============")
        print('胖子老板的老婆类被调用啦!要学会干家务')
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 需要干的家务是 %s" % (name, housework))
        print()
        print("=============== 结束调用 FatBossWife  ==============")


# 胖子老板的女儿类 继承 FatBoss FatBossWife类
class FatBossGril(FatBoss, FatBossWife):
    def __init__(self, name, hobby, housework):
        print('胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主')
        super().__init__(name, hobby, housework)


def main():

    print("打印FatBossGril类的MRO")
    print(FatBossGril.__mro__)

    print()
    print("=========== 下面按照 MRO 顺序执行super方法 ===========")
    gril = FatBossGril("胖子老板", "打斗地主", "拖地")

运行结果如下:

if __name__ == "__main__":
    main()
打印FatBossGril类的MRO

(<class '__main__.FatBossGril'>, <class '__main__.FatBoss'>, 
<class '__main__.FatBossWife'>, <class '__main__.FatFather'>, <class 'object'>)

=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主

=============== 开始调用 FatBoss  ======================
胖子老板的类被调用啦!

=============== 开始调用 FatBossWife  ==================
胖子老板的老婆类被调用啦!要学会干家务

=============== 开始调用 FatFather  ====================
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束

=============== 结束调用 FatFather  ===================
胖子老板 需要干的家务是 拖地

=============== 结束调用 FatBossWife  =================
胖子老板 的爱好是 打斗地主

=============== 结束调用 FatBoss  ======================

从上面的运行结果来看,我特意给每个类的调用开始以及结束都进行打印标识,可以看到。每个类开始调用是根据MRO顺序进行开始,然后逐个进行结束的。还有就是由于因为需要继承不同的父类,参数不一定。所以,所有的父类都应该加上不定参数*args , **kwargs ,不然参数不对应是会报错的。

三、注意事项

  • super().__init__相对于类名.init,在单继承上用法基本无差

  • 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,可以尝试写个代码来看输出结果

  • 多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错

  • 单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错

  • 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因文章来源地址https://www.toymoban.com/news/detail-754040.html

到了这里,关于python中super()方法的详细用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python中的super:调用父类的构造方法

     在子类构造方法中调用父类构造方法的两种方式: 1、未绑定的方法: 直接使用父类名来进行调用 ,即‘父类名.父类方法名(self,[参数1, 参数2,...])’ 2、 super() : 如果涉及多继承,该函数只能调用第一个直接父类的构造方法。super().父类方法名(self, [参数1, 参数2,...])或supe

    2024年02月15日
    浏览(59)
  • python调用父类方法的三种方式(super调用和父类名调用)

    父类名.方法名(self) super(子类名,self).父类方法名() super().父类方法名 注意:super()通过子类调用当前父类的方法,super默认会调用第一个父类的方法(适用于单继承的多层继承 如下代码: 如下代码: 上面代码运行结果: 针对这种情况,正确的做法是定义Person类自己的构造方法

    2024年02月06日
    浏览(59)
  • 【Python beautifulsoup】详细介绍beautifulsoup库的使用方法,包括安装方式、基本用法、常用方法和技巧,以及结合lxml和parsel的具体使用场景和区别。

    Python beautifulsoup库是一个强大的Web抓取和解析库,它提供了丰富的功能和简单易用的API,可以帮助我们处理HTML和XML文档,从中提取数据,进行数据清洗和处理。beautifulsoup库基于Python标准库中的html.parser模块,同时还可以与第三方解析库lxml和parsel配合使用,提供更高效和灵活的

    2024年02月04日
    浏览(63)
  • C语言中fopen的详细用法

    fopen是C语言中用于打开文件的函数,其原型为: 其中,filename是要打开的文件名,mode是打开文件的模式。fopen函数返回一个指向FILE类型的指针,该指针指向打开的文件。 fopen函数的mode参数有以下几种: \\\"r\\\":以只读方式打开文件。文件必须存在,否则打开失败。 \\\"w\\\":以写方式

    2024年02月11日
    浏览(24)
  • 【ES6】js 中class的extends、super关键字用法和避坑点

    在JavaScript中,使用class可以实现面向对象编程。其中,extends和super是两个非常重要的,它们分别用于实现类的继承和调用父类的方法。 一、extends extends用于实现类的继承,它可以让一个子类继承父类的属性和方法。使用extends时,需要指定要

    2024年02月09日
    浏览(34)
  • C语言中的static的用法(超级详细)

    🌹作者:云小逸 📝个人主页:[云小逸的主页] 📝码云:云小逸 (YunXiaoYi003) 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。希望

    2024年01月16日
    浏览(46)
  • 手把手QQ机器人制作教程,根据官方接口进行开发,基于Python语言制作的详细教程(更新中)

    QQ开放平台官方地址:https://q.qq.com/#/app/bot QQ开放平台包含:QQ机器人、QQ小程序、QQ小游戏,我们这边选择QQ机器人。 机器人类型:设置私域机器人或者公域机器人,当然公域机器人对于服务器的要求过高,我们这边选择 私域机器人 进行开发。 特别注意在选择沙箱频道的时候

    2023年04月08日
    浏览(61)
  • 【C语言】深入解密C语言组包与解包的用法、应用以及const的详细解说

    目录 一、sprintf 用于组包  应用1:按照规定格式组包  应用2:将数值类型转换成字符串类型  二、sscanf 用于解包  应用1:%d提取数值‘0’~‘9’   应用2:%s提取字符串(遇到\\\'\\0\\\' 空格 回车结束提取)  三、sscanf高级应用 1、跳过数据%*d %*s(*表示跳过该数据) 2、读取指定宽

    2024年02月16日
    浏览(29)
  • 浏览器开发者工具network用法,超详细讲解

    最近很多小伙伴说,不会用浏览器开发者工具,今天我们就一起来深入了解一下开发者工具。 以谷歌浏览器为例 谷歌浏览器开发者工具中的Network 是我们学习经常用到的,那么你都知道他们每个功能的意义吗? 因本人经常有360极速浏览器,谷歌内核,所以本文以360极速浏览器的

    2024年02月08日
    浏览(51)
  • Python的切片操作详细用法解析

    在利用Python解决各种实际问题的过程中,经常会遇到从某个对象中抽取部分值的情况,切片操作正是专门用于完成这一操作的有力武器。理论上而言,只要条件表达式得当,可以通过单次或多次切片操作实现任意切取目标值。切片操作的基本语法比较简单,但如果不彻底搞清

    2024年02月02日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包