2017-04-21 26 views
0

看看下面的例子上型.__甲混乱init__在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不是?
+0

嗯...'基地(参数)''调用.__基地...... init__' – ForceBru

+1

“为什么'基地.__ init__'被调用为'D2',即使我们没有创建'D2'的实例?“ - 因为你已经创建了一个'Base'的实例。这个例子是'D2'。 – user2357112

回答

2

Base.__init__被称为第一次,当你这样做:

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

你正在创建的Base一个实例,因此其__init__方法被调用,没什么希奇。

它被称为创建D2时,因为创建类调用元类的__init__方法的第二个时间(是的,该类的类的),这是Base; D2Base的一个实例。

由于D1Base的子类型/子类别,因此不需要D1而不是它的一个实例。

注意当你BaseD1,而不是它的父类的元类会发生什么:

class D1(object): 
    __metaclass__ = Base 
    pass 

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

我不熟悉'metaclass'是如何工作的。所以我仍然感到困惑,为什么当D2是Base的一个实例时调用Base .__ init__';甚至在阅读http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python之后,因为'__metaclass__'没有在这里使用。 – Jacky

+0

另一个问题:'__metaclass__'的位置是否重要? – Jacky

+0

[__metaclass__的基本原理](http://jfine-python-classes.readthedocs.io/en/latest/metaclass-attribute.html#the-basic-principle-of-the-metaclass) –