1 class A: 2 def test(self): 3 print("A --- test方法") 4 5 def demo(self): 6 print("A --- demo方法") 7 8 class B: 9 def test(self): 10 print("B --- test方法") 11 12 def demo(self): 13 print("B --- demo方法") 14 15 16 class C(A,B): 17 pass 18 19 20 c = C() 21 print(dir(c)) #dir()显示该类中所有的方法和属性 22 c.test() 23 c.demo() 24 print(C.__mro__) #向上查询顺序
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'demo', 'test'] A --- test方法 A --- demo方法 (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
单个调用父类的方法:
1 # coding=utf-8 2 3 print("******多继承使用类名.__init__ 发生的状态******") 4 class Parent(object): 5 def __init__(self, name): 6 print('parent的init开始被调用') 7 self.name = name 8 print('parent的init结束被调用') 9 10 class Son1(Parent): 11 def __init__(self, name, age): 12 print('Son1的init开始被调用') 13 self.age = age 14 Parent.__init__(self, name) 15 print('Son1的init结束被调用') 16 17 class Son2(Parent): 18 def __init__(self, name, gender): 19 print('Son2的init开始被调用') 20 self.gender = gender 21 Parent.__init__(self, name) 22 print('Son2的init结束被调用') 23 24 class Grandson(Son1, Son2): 25 def __init__(self, name, age, gender): 26 print('Grandson的init开始被调用') 27 Son1.__init__(self, name, age) # 单独调用父类的初始化方法 28 Son2.__init__(self, name, gender) 29 print('Grandson的init结束被调用') 30 31 gs = Grandson('grandson', 12, '男') 32 print('姓名:', gs.name) 33 print('年龄:', gs.age) 34 print('性别:', gs.gender) 35 36 print("******多继承使用类名.__init__ 发生的状态****** ")
结果:
******多继承使用类名.__init__ 发生的状态****** Grandson的init开始被调用 Son1的init开始被调用 parent的init开始被调用 parent的init结束被调用 Son1的init结束被调用 Son2的init开始被调用 parent的init开始被调用 parent的init结束被调用 Son2的init结束被调用 Grandson的init结束被调用 姓名: grandson 年龄: 12 性别: 男 ******多继承使用类名.__init__ 发生的状态******
父类会被多次调用,浪费大量的资源
MRO和super()用法:
1 print("******多继承使用super().__init__ 发生的状态******") 2 class Parent(object): 3 def __init__(self, name, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 4 print('parent的init开始被调用') 5 self.name = name 6 print('parent的init结束被调用') 7 8 class Son1(Parent): 9 def __init__(self, name, age, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 10 print('Son1的init开始被调用') 11 self.age = age 12 super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数 13 print('Son1的init结束被调用') 14 15 class Son2(Parent): 16 def __init__(self, name, gender, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 17 print('Son2的init开始被调用') 18 self.gender = gender 19 super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数 20 print('Son2的init结束被调用') 21 22 class Grandson(Son1, Son2): 23 def __init__(self, name, age, gender): 24 print('Grandson的init开始被调用') 25 # 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍 26 # 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因 super根据C3算法,每个类只调用一遍 27 # super(Grandson, self).__init__(name, age, gender) Grandson可以换成Son1或者其他,即 可以跳到指定的位置向上查询 28 super().__init__(name, age, gender) # 默认从Grandson开始查找MRO向上顺序 29 print('Grandson的init结束被调用') 30 31 print(Grandson.__mro__) 32 33 gs = Grandson('grandson', 12, '男') 34 print('姓名:', gs.name) 35 print('年龄:', gs.age) 36 print('性别:', gs.gender) 37 print("******多继承使用super().__init__ 发生的状态****** ")
运行结果:
******多继承使用super().__init__ 发生的状态****** (<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>) Grandson的init开始被调用 Son1的init开始被调用 Son2的init开始被调用 parent的init开始被调用 parent的init结束被调用 Son2的init结束被调用 Son1的init结束被调用 Grandson的init结束被调用 姓名: grandson 年龄: 12 性别: 男 ******多继承使用super().__init__ 发生的状态******
super总结:
1 super().__init__相对于类名.__init__,在单继承上用法基本无差 2 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果 3 多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错 4 单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错 5 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因