【问题标题】:A confusion on type.__init__ in Python 2Python 2 中 type.__init__ 的混淆
【发布时间】:2017-09-18 14:50:18
【问题描述】:

看看下面的例子

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 不被调用?

【问题讨论】:

  • Err... Base(arguments) 调用 Base.__init__...
  • "为什么Base.__init__ 会被D2 调用,即使我们还没有创建D2 的实例?" - 因为您创建了Base 的实例。该实例是D2

标签: python python-2.x metaclass


【解决方案1】:

Base.__init__ 在您第一次调用时被调用:

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

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

第二次创建D2时调用,因为创建一个类调用了元类(是的,类的类)Base__init__方法; D2Base 的一个实例。

D1 不调用它,因为 D1Base 的子类型/子类,而不是它的实例。

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

class D1(object):
    __metaclass__ = Base
    pass

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

【讨论】:

猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 2018-09-26
  • 2022-10-07
  • 1970-01-01
  • 2017-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多