2017-04-21 49 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) –