2012-09-30 33 views
13

在學習Python的數據模型時,我正在玩使用__new__方法從現有對象創建對象。下面是一些例子創建不同類型的新對象:來自現有對象的Python對象使用__new__

x = 2;  print type(x).__new__(x.__class__) 
x = {}; print type(x).__new__(x.__class__) 
x = [1,2]; print type(x).__new__(x.__class__) 
x = 2.34; print type(x).__new__(x.__class__) 
x = '13'; print type(x).__new__(x.__class__) 
x = 1.0j; print type(x).__new__(x.__class__) 
x = True; print type(x).__new__(x.__class__) 
x = (1,2); print type(x).__new__(x.__class__) 

但是,下面的三個實驗給我的錯誤:

x = None;   print type(x).__new__(x.__class__) 
x = lambda z: z**2; print type(x).__new__(x.__class__) 
x = object;   print type(x).__new__(x.__class__) 

的錯誤(分別)爲:

TypeError: object.__new__(NoneType) is not safe, use NoneType.__new__() 
TypeError: Required argument 'code' (pos 1) not found 
TypeError: type() takes 1 or 3 arguments 

這三個例子爲什麼不起作用? (注意:對於lambda示例,似乎我在調用__new__方法時必須傳入代碼片段,但我不知道如何執行此操作。)我正在使用Python 2.6。

請注意,我認識到這不一定是您想要在真實代碼中創建新對象的方式,但我的目的不切實際,而是理解底層對象方法的工作原理。

+1

什麼樣的錯誤表明它對我們有利。 –

+0

添加的消息,羅希特。感謝您的建議。 – rlandster

回答

14

沒什麼太特別的,只是對於某些類型而言,這種類型有一個默認的「空」對象,而對於其他類型則沒有。您的工作示例基本等同於:

int() 
dict() 
list() 
float() 
str() 
complex() 
tuple() 

。 。 。所有這些工作。最後三個例子基本上試圖創建新的NoneType,functiontype

  1. 由於獨立原因,無類型失敗,因爲無是單例---無類型類型只能有一個實例,即無對象。 (你得到的具體錯誤信息有點奇怪,但是如果你做了types.NoneType(),你會得到一條更直接的消息,說「無法創建NoneType實例」。)
  2. 失敗,因爲如你所見,它需要一個論點,而你不提供一個。你需要的是一個代碼對象,你可以從現有的函數或compile函數中獲得代碼對象。 (它還需要globals參數,這可能只是一個字典。)
  3. type失敗,因爲您沒有提供足夠的參數。您可以執行type(foo)以獲取foo的類型,或者使用type(name, bases, dict)創建新類型(即類)。

順便說一句,在你的最後一個例子中,你正在使用類型object,它本身就是一個類型。如果你改用x = object()(使x是一個單獨的對象而不是對象類型),那麼它將工作並創建一個「空白」對象。

需要記住的是,撥打__new__並不是那麼神奇。當你直接嘗試通過做someType()來實例化類型時會發生什麼。如果這種類型需要參數,調用__new__將失敗,就像任何其他函數調用將失敗,如果你沒有給出正確的參數,因爲type(x).__new__只是一個像任何其他函數一樣的函數。你可以看到這與用戶定義的類:

>>> class Foo(object): 
...  pass 
>>> x = Foo();   print type(x).__new__(x.__class__) 
<__main__.Foo object at 0x00EB0370> 
>>> class Foo(object): 
...  def __init__(self, someArg): 
...   pass 
>>> class Foo(object): 
...  def __new__(cls, someArg): 
...   return super(Foo, cls).__new__(cls) 
>>> x = Foo(2);   print type(x).__new__(x.__class__) 
Traceback (most recent call last): 
    File "<pyshell#32>", line 1, in <module> 
    x = Foo(2);   print type(x).__new__(x.__class__) 
TypeError: __new__() takes exactly 2 arguments (1 given) 

它在第一種情況下成功,因爲我的類不需要參數;它在第二類失敗,因爲第二類確實需要參數。

__new__不會因任何祕密原因失敗;它只是失敗,因爲你試圖實例化的類型需要參數才能構造一個實例。 (None的情況是唯一不同的情況,因爲None是Python中的一個特殊對象,所以這種情況是不合適的。)

+0

非常清楚地解釋了+1 – JamesSwift