Python 2 中对 type.__init__ 的混淆

A confusion on type.__init__ in Python 2

看看下面的例子

class Base(type):
    def __init__(cls, name, bases, dict_):
        print 'Base.__init__() with cls %s, name %s...' % (cls, name, )
        type.__init__(cls, name, bases, dict_)

M = Base('M', (object,), {})

class D1(Base):
    pass

class D2(M):
    pass

输出为

Base.__init__() with cls <class '__main__.M'>, name M...
Base.__init__() with cls <class '__main__.D2'>, name D2...

我对这个结果感到很困惑,

  1. 为什么 Base.__init__ 被调用为 D2,即使我们还没有创建 D2 的实例?
  2. 既然 Base.__init__ 被调用 D2,为什么 D1 不被调用?

Base.__init__ 第一次被调用时:

M = Base('M', (object,), {})

您正在创建 Base 的实例,因此它的 __init__ 方法被调用,不足为奇。

创建D2时第二次调用,因为创建class调用了metaclass[=36的__init__方法=](是的,class 的 class)是 BaseD2Base.

的实例

不为 D1 调用,因为 D1Base 的 subtype/subclass 而不是它的实例。

注意当您将 Base 设为 D1 的元 class 而不是它的超级 class 时会发生什么:

class D1(object):
    __metaclass__ = Base
    pass

# Base.__init__() with cls <class 'D1'>, name D1...