推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

Python中super函数用法实例分析

   2023-07-22 网络整理佚名1640
核心提示:本文实例讲述了中super函数用法。super函数是调用下一个父类(超类)并返回该父类实例的方法.通过调用super获得父类实例从而可以实现该实例的初始化函数.上面的super函数方法还可以这么写:super其实和通过父类来调用方法差不多.super方法实际是调用了cls的在MRO表中的下一个类.在MRO表中的超类初始化函数只执行了一次!(中的super用法详解):

本文通过示例介绍了 super 函数的使用。 分享给大家,供大家参考,如下:

这是一个高大上的函数。 如果你在13手册中使用太多,可能会显得你是23333高手。但实际上,它仍然很重要。 简单来说,super函数就是调用下一个父类(超类)并返回父类实例的方法。 这里下一个概念是指后面介绍的MRO表。

help介绍如下:

super(type, obj) -> 绑定 super ; (对象,类型)

超级(类型)->超级

super(type, type2) -> 绑定 super ; (类型2,类型)

用于调用:

C(B)类:

def meth(self, arg):

超级(C,自我).meth(arg)

可见super有3种用法。 第一个参数始终是调用父类的类,第二个参数是可选的(返回未绑定的父类对象),也可以是该类的实例对象或子类。 最后,它返回父类的实例(绑定或未绑定)。 中,super函数多了一个直接super()的用法,相当于super(type,第一个参数)。

另外,在py2中,super只支持新类(new-style class,继承自)。

为什么称父类为?

类继承时,如果重新定义一个方法,该方法会覆盖父类中对应的同名方法。 通过调用父类实例,可以在子类中同时实现父类的功能。 例如:

# Should be new-class based on object in python2.
class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  super(B, self).__init__()
  print "leave B"
>>> b = B()
enter B
enter A
leave A
leave B

实例的初始化功能可以通过调用super获取父类实例来实现。 这在实践中太常见了(因为必须继承父类的功能,并且必须添加新的功能)。

直接使用父类调用的区别

其实上面的super函数方法也可以写成如下:

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  A.__init__(self)
  print "leave B"

直接使用父类名来调用父类的方法其实也是可行的。 至少在上面的例子中,它们现在是一样的。 该方法也是旧式类中调用父类的唯一方法(旧式类没有super)。

通过父类名调用方法是非常常见和直观的。 不过它的效果和super还是有区别的。 例如:

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  A.__init__(self)
  print "leave B"
class C(A):
 def __init__(self):
  print "enter C"
  A.__init__(self)
  print "leave C"
class D(B,C):
 def __init__(self):
  print "enter D"
  B.__init__(self)
  C.__init__(self)
  print "leave D"
>>> d=D()
enter D
enter B
enter A
leave A
leave B
enter C
enter A
leave A
leave C
leave D

可以发现A的初始化函数被执行了两次。 因为我们需要同时实现B和C的初始化函数,所以我们分别调用了两次,这是必然的结果。

但如果改写为 super? 呢?

class A(object):
 def __init__(self):
  print "enter A"
  print "leave A"
class B(A):
 def __init__(self):
  print "enter B"
  super(B,self).__init__()
  print "leave B"
class C(A):
 def __init__(self):
  print "enter C"
  super(C,self).__init__()
  print "leave C"
class D(B,C):
 def __init__(self):
  print "enter D"
  super(D,self).__init__()
  print "leave D"
>>> d=D()
enter D
enter B
enter C
enter A
leave A
leave C
leave B
leave D

会发现所有父类ABC都只执行了一次,A的初始化并没有像之前那样执行两次。

然后,我发现了一个很奇怪的事情:父类的执行是按照BCA的顺序,都是先输入再统一出来的。 这是MRO表的问题,稍后会讨论。

如果没有多重继承的话,super其实就类似于通过父类调用方法。 不过super还有一个好处:B继承A的时候写成A,如果你想根据自己的需要重构全部继承E,那么你就得全部改一次!

,可以发现super并不是那么简单。

维修工作台

什么是MRO'可以通过以下方式调用:

>>> D.mro() # or d.__class__.mro() or D.__class__.mro(D) 
[D, B, C, A, object]
>>> B.mro()
[B, A, object]
>>> help(D.mro)
#Docstring:
#mro() -> list
#return a type's method resolution order
#Type:  method_descriptor

MRO是类的方法分析序列表,其实就是继承父类的方法时的序列表(也可以理解为类继承序列表)。

这个表有什么用呢? 首先了解一下 super 的实际作用:

def super(cls, inst):
 mro = inst.__class__.mro()
 return mro[mro.index(cls) + 1]

换句话说,super方法实际上调用了MRO表中调用cls的下一个类。 如果是简单的一行单继承的话,就是父类->父类一一对应。 但对于多重继承,就需要遵循MRO表中的顺序。 以上面D的调用为例:

d 的初始化

-> D(进入D)超级(D,自我)

-> 父类B(输入B)super(B,self)

-> 父类C(输入C)super(C,self)

-> 父类A (进入A) (退出A) # 如果有则继续 super(A, self) -> (停止)

->(C出口)

-> (B出口)

->(出口D)

因此,MRO表中的超类初始化函数只执行一次!

那么,MRO的顺序是如何确定的呢? 关于这一点,请参考官方说明2.3命令。 基本上就是计算每个类的MRO(从父类到子类的顺序),然​​后合并成一行。 请遵循以下规则:

在MRO中,基类总是出现在派生类的后面。 如果有多个基类,则基类的相对顺序保持不变。 这个原则包括两点:

1.基类总是在派生类后面

2、类定义的继承顺序影响相对顺序。

假如有如下继承(super的详细用法在):

/\

/A

| /\

B-1 C-2 D-2

\//

E-1 /

\ /

那么MRO就是:F->E->B->C->D->A->

怎么解释呢?

按照官方的方法是:

L(O) = O
L(B) = B O
L(A) = A O
L(C) = C A O
L(D) = D A O
L(E) = E + merge(L(B),L(C))
  = E + merge(BO,CAO)
  = E + B + merge(O,CAO)
  = E + B + C + merge(O,AO)
  = E + B + C + A + merge(O,O)
  = E B C A O
L(F) = F + merge(L(E),L(D))
  = F + merge(EBCAO,DAO)
  = F + EBC + merge(AO,DAO)
  = F + EBC + D + merge(AO,AO)
  = F EBC D AO

看起来很复杂..但仍然可以得出,在MRO中,基类总是出现在派生类的后面。 如果有多个基类,则基类的相对顺序保持不变。 所以,我个人认为这样思考是可以的:

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON