类别:Python / 日期:2019-12-02 / 浏览:92 / 评论:0

一、零丁挪用父类的要领

需求:编写一个类,然后再写一个子类举行继续,运用子类去挪用父类的要领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() 要领的运用。

2.1 形貌

super() 函数是用于挪用父类(超类)的一个要领。

super 是用来处理多重继续题目的,直接用类名挪用父类要领在运用单继续的时刻没题目,然则假如运用多继续,会涉及到查找递次(MRO)、反复挪用(钻石继续)等各种题目。

MRO 就是类的要领剖析递次表, 实在也就是继续父类要领时的递次表。

相干引荐:《Python视频教程》

2.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)

Python2.x 实例:

class A(object):   # Python2.x 记得继续 object
    pass
class B(A):
    def add(self, x):
        super(B, self).add(x)

2.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 ,所以单继续是没题目的。

那末假如多继续的话,会有什么题目呢?

2.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  ========================")
# 胖子老板的妻子类 继续 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要领,只需写一句话便实行了悉数父类的要领,这也是为 何多继续须要悉数传参的一个缘由。

四、演习

以下的代码的输出将是什么? 说出你的答案并诠释。

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)
1 1 1
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
1 2 1

注重:Child1已具有了属于本身的x

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
3 2 3

以上就是Python中的super()要领详解的细致内容,更多请关注ki4网别的相干文章!

打赏

感谢您的赞助~

打开支付宝扫一扫,即可进行扫码打赏哦~

版权声明 : 本文未使用任何知识共享协议授权,您可以任何形式自由转载或使用。

 可能感兴趣的文章

评论区

发表评论 / 取消回复

必填

选填

选填

◎欢迎讨论,请在这里发表您的看法及观点。