列子python
# 胖子老板的父类 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)直接调用父类的方法。算法
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,可是若是使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。python3.x
用法: print(最后子类名.mro()) 或者 print(最后子类名.__mro__)
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。函数
super(type[, object-or-type])code
type -- 类
object-or-type -- 类,通常是 self排序
Python 3 可使用直接使用 super().xxx 代替 super(Class, self).xxx :继承
例子以下:it
# 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)
那么为何说单继承直接使用就能够呢?由于super()方法若是多继承的话,会涉及到一个MRO(继承父类方法时的顺序表) 的调用排序问题。class
# 胖子老板的父类 # 胖子老板的父类 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("胖子老板", "打斗地主") if __name__ == "__main__": main()
上面的代码使用 FatBoss.__mro__ 能够打印出 FatBoss这个类通过 python解析器的 C3算法计算事后的继承调用顺序。
(<class 'main.FatBoss'>, <class 'main.FatFather'>, <class 'object'>)
从上面的结果 (<class 'main.FatBoss'>, <class 'main.FatFather'>, <class 'object'>) 能够看出,super() 方法在 FatBoss 会直接调用父类是 FatFather ,因此单继承是没问题的。object
每一个类开始调用是根据MRO顺序进行开始,而后逐个进行结束的。
还有就是因为由于须要继承不一样的父类,参数不必定。
因此,全部的父类都应该加上不定参数*args , **kwargs ,否则参数不对应是会报错的。
# 胖子老板的父类 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'>)
关于super()使用的注意事项: 1.super().__init__相对于类名.__init__,在单继承上用法基本无差 2.但在多继承上有区别,super方法能保证每一个父类的方法只会执行一次,而使用类名的方法会致使方法被执行屡次,能够尝试写个代码来看输出结果 3.多继承时,使用super方法,对父类的传参数,应该是因为python中super的算法致使的缘由,必须把参数所有传递,不然会报错 4.单继承时,使用super方法,则不能所有传递,只能传父类方法所需的参数,不然会报错 5.多继承时,相对于使用类名.__init__方法,要把每一个父类所有写一遍, 而使用super方法,只需写一句话便执行了所有父类的方法,这也是为什么多继承须要所有传参的一个缘由