一、零丁挪用父类的要领
需求:编写一个类,然后再写一个子类举行继续,运用子类去挪用父类的要领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网别的相干文章!