5 super 没那么简单 - ??????????????

      <kbd id='hlUorKxEL'></kbd><address id='hlUorKxEL'><style id='hlUorKxEL'></style></address><button id='hlUorKxEL'></button>

              <kbd id='hlUorKxEL'></kbd><address id='hlUorKxEL'><style id='hlUorKxEL'></style></address><button id='hlUorKxEL'></button>

                  首页

                  super 没那么简单

                  发表时间:2018-02-15 10:24 来源:??????????????

                  classD(B,C):

                  单继承

                  这次的输出如下:

                  # d.n = 11

                  # 第四步

                  classC(A):

                  # self == d, self.n == d.n == 5

                  def add(self,x):

                  <class'super'>

                  selfis<__main__.Dobjectat0x10ce10e48> @C.add

                  当我们调用 super() 的时候●◇┯,实际上是实例化了一个 super 类№◎┲。你没看错№■△§, super 是个类┯■╀,既不是关键字也不是函数等其他数据结构:

                  所以■╂┲■,你如果用的是 Python 2 的话┳┳◆★,记得将本文的 super() 替换为 suepr(Class, self) §╃╃★。

                  print('self is {0} @C.add'.format(self))

                  def __init__(self):

                  print('self is {0} @D.add'.format(self))

                  def __init__(self):

                  self.n= 4

                  print(b.n)

                  self.n= 5

                  classB(A):

                  selfis<__main__.Dobjectat0x10ce10e48> @D.add

                  super().add(m)

                  # Python 2

                  def add(self,m):

                  def __init__(self):

                  selfis<__main__.Bobjectat0x106c49b38> @B.add

                  19

                  print('self is {0} @B.add'.format(self))

                  # 默认◇§●, Python 3

                  多继承中 super 的工作方式

                  super().add(m)

                  def add(self,m):

                  selfis<__main__.Dobjectat0x10ce10e48> @B.add

                  print('self is {0} @D.add'.format(self))

                  def __init__(self):

                  classC(A):

                  selfis<__main__.Dobjectat0x10ce10e48> @A.add

                  你觉得执行下面代码后◎◆╂┳, b.n 的值是多少呢?

                  self.n= 2

                  def add(self,m):

                  print('self is {0} @A.add'.format(self))

                  def __init__(self):

                  当这样调用时: :

                  print('self is {0} @C.add'.format(self))

                  def add(self,m):

                  15

                  self.n= 2

                  你说对了吗?你可能会认为上面代码的输出类似:

                  super 只会从 C 之后查找■╃╀●,即: 只会在 D 或 E 或 object 中查找 foo 方法●△。

                  super(B,self).add(x)

                  MRO 指的是 type(obj) 的 MRO, MRO 中的那个类就是 a_type , 同时 isinstance(obj, a_type) == True ┲◆★■。

                  下面的代码又输出啥呢?

                  在单继承中 super 就像大家所想的那样★●★◆,主要是用来调用父类的方法的★◆◇◎。

                  super().add(m)

                  那么┲★№, super() 实际上做了啥呢?简单来说就是:提供一个 MRO 以及一个 MRO 中的类 C △※, super() 将返回一个从 MRO 中 C 之后的类中查找方法的对象╀◎※┲。

                  # d.n = 11

                  print(d.n)

                  # 从 D 之后的 [B, C, A, object] 中查找 add 方法

                  也就是说┳◆,查找方式时不是像常规方法一样从所有的 MRO 类中查找★┲╂,而是从 MRO 的 tail 中查找§№┳。

                  # 来自 D.add 中的 super

                  d.add(2)

                  # 默认╂┳△┳,Python 3

                  这次我们再定义一个 class C■■╃,一个 class D:

                  # 来自 D.add 中的 super

                  # Python 2

                  self.n+= 3

                  self.n+= 3

                  >>> s= super(A)

                  >>>

                  # self == d, self.n == d.n == 5

                  def __init__(self):

                  selfis<__main__.Dobjectat0x10ce10e48> @C.add

                  # 第二步

                  # self == d, self.n == d.n == 5

                  def add(self,m):

                  # 从 B 之后的 [C, A, object] 中查找 add 方法

                  selfis<__main__.Dobjectat0x10ce10e48> @A.add

                  # 来自 B.add 中的 super

                  再回到前面的

                  # 等价于 suepr(B, self).add(m)

                  pass

                  下面我们来具体分析一下:

                  d= D()

                  classA:

                  selfis<__main__.Dobjectat0x10ce10e48> @D.add

                  这个结果说明了两个问题:

                  D.mro()== [D,B,C,A,object]

                  classB(A):

                  # 从 C 之后的 [A, object] 中查找 add 方法

                  # 第六步

                  print(d.n)

                  举个栗子, 有个 MRO: :

                  def add(self,m):

                  # self 的 MRO 是 [D, B, C, A, object]

                  classB(A):

                  # self 的 MRO 是 [D, B, C, A, object]

                  # d.n == 7

                  d= D()

                  # 第三步

                  # d.n = 7

                  selfis<__main__.Dobjectat0x10ce10e48> @B.add

                  >>> classA: pass

                  多继承

                  self.n+= 4

                  # 等价于 super(D, self).add(m)

                  defadd(self,m): defadd(self,m): defadd(self,m): defadd(self,m):

                  classD(B,C):

                  在大多数情况下┯╀●△◆, super 包含了两个非常重要的信息: 一个 MRO 以及 MRO 中的一个类■●★※。当以如下方式调用 super 时: :

                  classA(object):

                  self.n+= m

                  selfis<__main__.Dobjectat0x10ce10e48> @B.add

                  在开始之前我们来约定一下本文所使用的 Python 版本§◎■。默认用的是 Python 3╀╃№╀╃,也就是说:本文所定义的类都是新式类■╀◇。如果你用到是 Python 2 的话◎┲┲※,记得继承 object:

                  classD(B,C): classB(A): classC(A): classA:

                  ...

                  约定

                  b= B()

                  d.n== 5

                  # d.n = 14

                  Python 3 和 Python 2 的另一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :

                  [A,B,C,D,E,object]

                  def add(self,m):

                  # 第七步

                  super().add(m)

                  super 是个类

                  selfis<__main__.Dobjectat0x10ce10e48> @A.add

                  self.n= 3

                  19

                  print(d.n)

                  pass

                  # 第五步

                  def add(self,x):

                  print('self is {0} @B.add'.format(self))

                  print('self is {0} @A.add'.format(self))

                  selfis<__main__.Dobjectat0x10ce10e48> @D.add

                  现在你知道为什么 d.add(2) 后 d.n 的值是 19 了吧 ;)

                  • D 的 MRO 是: [D, B, C, A, object] △┲№。 备注: 可以通过 D.mro() (Python 2 使用 D.__mro__ ) 来查看 D 的 MRO 信息)
                  • 详细的代码分析如下:

                  classA:

                  classA:

                  8

                  super().add(x)

                  def __init__(self):

                  为什么会跟预期的不一样呢?下面我们将一起来看看 super 的奥秘┳◎◆╀。

                  self.n+= 5<------6.self.n+= 3<----5.self.n+= 4<----4.<--|

                  selfis<__main__.Bobjectat0x106c49b38> @A.add

                  # d.n = 14

                  了吧 ;)

                  >>> type(s)

                  self.n= 5

                  d.add(2)

                  self.n= 4

                  super(type1,type2)

                  b.add(2)

                  classB(A):

                  self.n+= m

                  self.n+= 5

                  super().add(m)

                  d= D()

                  1. super().add(m) 确实调用了父类 A 的 add 方法╀◇●◎●。
                  2. super().add(m) 调用父类方法 def add(self, m) 时, 此时父类中 self 并不是父类的实例而是子类的实例, 所以 b.add(2) 之后的结果是 5 而不是 4 №◎。

                  不知道这个结果是否和你想到一样呢?下面我们来看一个多继承的例子★★※●。

                  执行结果如下:

                  d.add(2)

                  调用过程图如下:

                  super(a_type,obj)

                  d.add(2)

                  self.n+= 5

                  d= D()

                  # 第一步

                  super().add(m)

                  # 等价于 suepr(C, self).add(m)

                  (14+5=19)(11+3=14)(7+4=11)(5+2=7)

                  # self.n = 19

                  self.n= 3

                  如果还有其他不兼容 Python 2 的情况◆◆┯△╂,我会在文中注明的★§№。

                  现在你可能已经有点眉目┲№┲┯,为什么输出会是 :

                  # self 的 MRO 是 [D, B, C, A, object]

                  super().add(m)1.---> super().add(m)2.---> super().add(m)3.---> self.n+= m

                  def __init__(self):

                  That’s all! 希望这篇文章能对你有所帮助 ;)

                  MRO 指的是 type2 的 MRO, MRO 中的那个类就是 type1 ★△※,同时 issubclass(type2, type1) == True ┲◆№△。

                  id="mp-editor">

                  说到 super№※╀, 大家可能觉得很简单呀※●◆╂╀,不就是用来调用父类方法的嘛№※┳。如果真的这么简单的话也就不会有这篇文章了◇◇,且听我细细道来◇。😄

                  def add(self,m):

                  self.n+= 4

                  参考资料

                  §※№,╀△┯。

                  相关阅读