Python面向对象中super用法与MRO机制(3)

super(E , F()).fun() # 输出结果:B.fun super(D , F()).fun() # 输出结果:A.fun super(F , F()).fun() # 输出结果:D.fun

  再回顾一下__mro__的顺序:F->D->A->E->B->C->object,发现规律没?调用的都是type对应的类在__mro__顺序中的下一个类的fun方法。所以,我们可以通过type参数来指定调用父类的范围。

  再让type保持不变,obj尝试不同的实例:

super(B , F()).fun() # 输出结果:C.fun super(B , E()).fun() # 输出结果:C.fun super(B , B()).fun() # 这是错误的,会报错

  发现规律了吗?上面这个类继承关系太简单,可能规律并不明显。事实上,obj参数指定的是用那个类的__mro__属性。

  好了,我们现在回到图2中使用super()之后的代码,来解释一下为什么输出顺序是A->C->B->D。首先我们要明白,D类的__mro__顺序是D->B->C->A,在D类中调用fun方法,然后在D类fun方法中遇到super(D , self).fun(),这个self指的是D类的实例化对象,所以用的是D类的__mro__顺序,而且指明位置是D后面也就是B类,所以继续调用B类的fun方法,遇到super(B , self).fun(),这时候需要注意,这里的self还是原来的D类实例(千万注意不是B类实例),所以还是用D类的__mro__顺序,那就继续调用下一个C类的fun方法,同理继续调用下一个父类,也就是A类的fun方法,执行完A类的fun方法后,回到C的fun方法中,打印输出,然后回到B类的fun方法,知道D类的fun方法打印输出完。懂了吗?

4.2 super()

  super()事实上是懒人版的super(type , obj),这种方式只能用在类体内部,Python会自动把两个参数填充上,type指代当前类,obj指导当前类的实例对象,相当于super(__class__ , self)。所以,以下三种代码是完全等效的:
  代码一:

class B(A): def fun(self): super().fun() print('B.fun')

  代码二:

class B(A): def fun(self): super(B , self).fun() print('B.fun')

    代码三:

class B(A): def fun(self): super(__class__ , self).fun() print('B.fun')

4.3 super(type_1 , type_2)

  当super传入的两个参数都是类名是,type_2必须是type_1的子类。功能上与super(type , obj)有什么不同呢?我们继续上一小节的代码输出测试:

print(super(F , F())) #输出结果为:<super: <class 'F'>, <F object>> print(super(F , F)) #输出结果为:<super: <class 'F'>, <F object>>

  输出结果是一样的,那你就以为super(type_1 , type_2)与super(type , obj)一样吗?看下面输出:

print(super(F , F()).fun()) #输出结果为:D.fun print(super(F , F).fun()) # 报错:TypeError: fun() missing 1 required positional argument: 'self'

  所以,super(type_1 , type_2)与super(type , obj)有区别,在看一下下列输出:

print(super(F , F()).fun)# 输出结果:<bound method D.fun of <__main__.F object at 0x000001BD44A98B38>> print(super(F , F).fun) # 输出结果:<function D.fun at 0x000001BD44A9EE18> print(D.fun) # 输出结果:<function D.fun at 0x000001BD44A9EE18>

  所以,当super传入的两个传输都是类时,得到的就是一个指向继承顺序下的类的代理,并未绑定实例,要调用D类的fun方法,还需传入实例:

print(super(F , F).fun(F())) #输出结果:D.fun

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/fd49c6ee62718101674b2e72a81f702d.html