如果定义一个没有 __init__ 方法的类会发生什么?

Eas*_*sun 5 python multiple-inheritance method-resolution-order

假设我定义了四个类如下:

(该代码已经在 Python 3.6.5 上进行了测试。但是,我希望它也可以在 Python 2.7.x 上使用from __future__ import print_function

In [1]: class A(object):
   ...:     pass
   ...: 
   ...: class B(object):
   ...:     def __init__(self, value):
   ...:         print('B(value=%s)' % value)
   ...: 
   ...: class C(A):
   ...:     def __init__(self, value):
   ...:         print('C(value=%s)' % value)
   ...:         super(C, self).__init__(value)
   ...: 
   ...: class D(A, B):
   ...:     def __init__(self, value):
   ...:         print('D(value=%s)' % value)
   ...:         super(D, self).__init__(value)
   ...:         

In [2]: C.mro()
Out[2]: [__main__.C, __main__.A, object]

In [3]: D.mro()
Out[3]: [__main__.D, __main__.A, __main__.B, object]
Run Code Online (Sandbox Code Playgroud)

注意两点:

  1. class A没有__init__方法;

  2. A根据 mro 信息,C 和 D 具有相同的后继。

所以我想这两个super(C, self).__init__(value)super(D, self).__init__(value)将触发__init__中定义的方法A

然而,下面的结果让我很困惑!

In [4]: C(0)
C(value=0)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-75d9b7f7d447> in <module>()
----> 1 C(0)

<ipython-input-1-5252938615c6> in __init__(self, value)
      9     def __init__(self, value):
     10         print('C(value=%s)' % value)
---> 11         super(C, self).__init__(value)
     12 
     13 class D(A, B):

TypeError: object.__init__() takes no parameters

In [5]: D(1)
D(value=1)
B(value=1)
Out[5]: <__main__.D at 0x2a6e8755b70
Run Code Online (Sandbox Code Playgroud)

我们可以看到class D初始化成功,而class C失败。

class C和之间的不同行为是class D什么?

编辑我不认为我的问题是关于 mro(实际上我或多或少知道关于 python 的 mro),我的问题是关于__init___方法的不同行为。

EDIT2我很傻,这是关于先生的。

谢谢你的帮助。

Mis*_*agi 7

  1. A没有单独的__init__方法 - 它是通过A`s own查找的mro

    >>> A.__init__ is object.__init__
    True
    
    Run Code Online (Sandbox Code Playgroud)
  2. B 类有一个单独的__init__方法 - 它不需要遍历mro.

    >>> B.__init__ is object.__init__
    False
    
    Run Code Online (Sandbox Code Playgroud)

请注意,区别在于拥有继承 __init__。仅仅因为A.__init__可以提供并不意味着A__init__本身就有一个方法。

  1. 当 C 查找其 时super().__init__,会尝试以下操作:

    • C.__init__ 被跳过
    • A.__init__ 不存在
    • object.__init__ 存在并被称为
  2. 当 D 查找其 时super().__init__,会尝试以下操作:

    • D.__init__ 被跳过
    • A.__init__ 不存在
    • B.__init__ 存在并被称为
    • object.__init__ 从不抬头

这种差异是使用super而不是显式基类的主要点。它允许将专门的类插入到层次结构中(示例)。