• python3面向对象(2)之super()


    super()是一个什么鬼?干什么用的?打开菜鸟教程看一下super()的简介;第一句话就是:super()函数是用来调用父类(超类)的一个方法。嗯哦;原来是一个函数可以返回一个父类的方法:于是我就这样理解了,那么如果是多继承呢,是返回所有父类的被调用的方法吗?一个疑问?看看下面的代码(先定义一个人类,然后定义一个男人,一个女人,一个儿子)

    class Person(object):     #定义一个人类,继承objec
        def __init__(self):
            print("我要好好学习")
    
        def study(self):
            print("我要学好语言")
    
    
    class man(Person):   #定义一个男人,继承人类
        def __init__(self):
            print("我是男人我要好好学习")
    
        def study(self):
            print("我要学好数学")
            
    
    
    class woman(Person):    #定义一个女人,继承人类
        def __init__(self):
            print("我是女人我要好好学习")
    
        def study(self):
            print("我要学好英语")
          
    
    class son(man,woman):  #定义一个儿子,继承男人和女人
        def __init__(self):
            print("我是儿子我要好好学习")
    
        def study(self):
            print("我要学好化学和物理")
    # woman.study(self) # man.study(self) super().study() # def study1(self): # print("我要学好英语") son1 = son() son1.study() # son1.study1()
    解释:先定义一个人类,定义一个方法:我要学好语言;然后定义一个男人:我要学好数学;再定义一个女人:我要学好英语;最后定义一个儿子学好化学和物理;在定义方法的时候我们都使用了study函数;所以子类的函数
    会覆盖父类的函数;最后实例化一个son1的对象调用study函数只会输出:我要学好化学和物理;但是这个时代光会这两门也不行啊;还得学好英语啊,那么怎么办呢? ok 简单
    
    在这个son的类中增加一个study1函数不就完了嘛,嗯,对确实完了;但是这样却增加了不必要的代码啊,学习英语这件事woman类中不是有了吗?我们不能直接使用这里的吗?当然可以,于是有了第二种方法:
    
    在son的类中的study函数中增加了 woman.study(self) 这句好相当于直接调用woman类中的study函数 同理也可以直接调用man类中的study函数;这样就不用创建新函数了;这种等于直接调用。我们还可以使用另外
    一种方式来调用man和woman中的study函数即:super().study();前面两种我们已经注释掉了我们只研究最后一种;即出现了上面的代码;那么这段代码会
    出现什么呢?(反正我一开始觉得super()不是调用父类的方法嘛,既然son有两个父类,两个父类的study函数一起调用了呗,可是结果呢)
    

     代码执行结果:

    我是儿子我要好好学习
    我要学好化学和物理
    我要学好数学
    

     噫噫噫,不对啊,和我想的不一样啊,只返回了man类中的方法;没有返回woman类中的方法啊;这是什么情况呢?一百的问号????

    于是查看了很多的博客,毕竟还是有很多大神的嘛我们要向前辈们学习啊,于是对super()又有了新的认识:我们返回文章的第一句话,super()是个什么鬼?从新解释一下:super()不是一个函数而是一个类,super()相当于这个类调用了自己的初始化函数,返回了一个对象;这个对象是干嘛的呢,用来调用实例化对象中的mro()序列中的下一个  的  类的指定的类中的方法(mro()返回的是一个:方法解析顺序列表)估计又懵了,那么我们先打印一下:son.mro()

    [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
    

    实际上打印出来的就是son的继承父类的顺序(son---man---woman---Person---object)

    那么以本例来说在son中写了super(),那么son的下一个mro当然就是man类,所以就返回了man类中的study方法了。这就是上面那个疑问的解答了;那么问题又来了如果我在man类中也写了super().study(),那么接下来会打印什么呢?无非就两个可能一个是打印Person中的sutdy方法另一个可能就是打印woman类中的study方法(为什么是这两种呢,如果我们是以son为出发点man的下一个mro当然是woman;但是我们现在是把super().study()写在了man类中这个时候好像以man类为出发点也说的过去啊,那么我们先打印一下man,mro()。)

    class man(Person):
        def __init__(self):
            print("我是男人我要好好学习")
    
        def study(self):
            print("我要学好数学")
            super().study()
    
    结果:
    [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
    

     果然man的下一个mro是Person而不是woman啊,如果我们执行上面的代码最终到底是打印person呢还是woman呢?看结果:

    我是儿子我要好好学习
    [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
    [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
    我要学好化学和物理
    我要学好数学
    我要学好英语
    

     打印出来的是我要学好英语是woman中的(而不是person中的);如果我们在woman类中也一起写上super(),那么:

    class Person(object):
        def __init__(self):
            print("我要好好学习")
    
        def study(self):
            print("我要学好语言")
    
    
    class man(Person):
        def __init__(self):
            print("我是男人我要好好学习")
    
        def study(self):
            print("我要学好数学")
            super().study()
    
    
    class woman(Person):
        def __init__(self):
            print("我是女人我要好好学习")
    
        def study(self):
            print("我要学好英语")
            super().study()
    
    class son(man,woman):
        def __init__(self):
            print("我是儿子我要好好学习")
    
        def study(self):
            print("我要学好化学和物理")
            # woman.study(self)
            # man.study(self)
    
            super().study()
    
        # def study1(self):
        #     print("我要学好英语")
    
    
    son1 = son()
    print(son.mro())
    print(man.mro())
    son1.study()
    # son1.study1()
    

     结果:

    我是儿子我要好好学习
    [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
    [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
    我要学好化学和物理
    我要学好数学
    我要学好英语
    我要学好语言
    

     看一下结果就知道了先打印了man类中的study方法,之后打印了woman类中的方法;最后打印了Person类中的study方法;所以到这里暂时得到一个结论:super()不是指父类(对于man类来说Person应该是父类)而只指以实例化对象为起点的mro序列中的下一个。

    那么我们把上面的代码再来改一改,如果我把man类中的super()注释掉了,但是woman类中保留着super()会又什么样的的结果呢:

    class Person(object):
        def __init__(self):
            print("我要好好学习")
    
        def study(self):
            print("我要学好语言")
    
    
    class man(Person):
        def __init__(self):
            print("我是男人我要好好学习")
    
        def study(self):
            print("我要学好数学")
            # super().study()
    
    class woman(Person):
        def __init__(self):
            print("我是女人我要好好学习")
    
        def study(self):
            print("我要学好英语")
            super().study()
    
    class son(man,woman):
        def __init__(self):
            print("我是儿子我要好好学习")
    
        def study(self):
            print("我要学好化学和物理")
            # woman.study(self)
            # man.study(self)
    
            super().study()
    
        # def study1(self):
        #     print("我要学好英语")
    
    
    son1 = son()
    
    print(son.mro())
    print(man.mro())
    
    son1.study()
    
    
    # son1.study1()
    

     结果:

    我是儿子我要好好学习
    [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
    [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
    我要学好化学和物理
    我要学好数学
    

     结果是man类中的sutdy方法打印出来了然而woman和Person类中的study方法没有打印出来;相当与 son--man--woman中在man这里打断了,然后后面的也就不执行了。

    好吧就到这里吧由于刚开始学习python,对于super()理解的还有很多不到位的地方;以后这篇文章还需要改进,暂时理解到这个程度。

  • 相关阅读:
    PHP静态页生成
    svn部署web项目
    Nginx出现403 forbidden
    Node-red的基础使用——inject/debug/function的使用(1)
    功能/性能测试报告的编写格式及模板
    node-red在不同环境安装步骤
    node-red实现接口自动化测试——初步认识
    docker删除image
    django测试开发,例一个接口的开发逻辑
    django测试平台开发,登录,验证,退出
  • 原文地址:https://www.cnblogs.com/yan-peng/p/9961384.html
Copyright © 2020-2023  润新知