2012-11-23 37 views
1

我對python文檔here下面的例子有些困惑。Python:當cls不是float時,爲什麼會浮動.__ new __(cls)?

>>> class inch(float): 
...  "Convert from inch to meter" 
...  def __new__(cls, arg=0.0): 
...   return float.__new__(cls, arg*0.0254) 
... 
>>> print inch(12) 
0.3048 
>>> 

大概,float是這裏定義的實際的float類,它定義在Python內部的某處。當我們調用float.__new__(cls, argument)時,我們狡猾地調用返回給定參數的float實例的函數,但我們將它傳遞給inch類而不是float類。由於英寸課程沒有做任何事情,爲什麼這個工作?

回答

6

因爲inch子類浮動,它滿足所有的float.__new__()實例工廠有要求。 __new__(cls) static method的作用是創建第一個參數的實例,而不是它自己的類。

請注意「靜態方法」一詞。 __new__工廠實際上只是一個專門的功能,只是出於繼承的原因才與類相關聯。換句話說,它是一個在面向對象層次結構中發揮得很好的函數。你應該通過super()找到它,或者直接調用它(如這裏所做的那樣)。下面實際上是一點點更Python:

def __new__(cls, arg=0.0): 
    return super(inch, cls).__new__(cls, arg*0.0254) 

,因爲這會稱之爲「正確的」 __new__功能,如果inch是在多重繼承層次中使用;在這個簡單的例子中,它最終會調用float.__new__。因此,__new__(cls, ...)預計將創建cls類型的實例。爲什麼然後把它和一個類聯繫起來,而不是把它變成一個更通用的函數呢?因爲在float.__new__(cls, value)的情況下,它不僅創建cls類型的新實例,還將其初始值設置爲value。爲了實現這個目標,float.__new__(...)需要深入瞭解float類的外觀。因爲inch()float()的一個子類,所以它也具有完全相同的必需位,因此它們也是float(),因此當float.__new__()工廠創建新的inch實例時,所有這些位都會使其成爲inch()實例。需要

+0

太棒了!這使得現在更有意義。所以,爲了確保我現在能理解 - __new__是一種靜態方法,也就是說它對'自我'沒有興趣(也沒有理由)。當我爲這個特定的類覆蓋它時,它可能保持靜態(因爲很難有一個需要實例的__new__方法)。如何知道沒有任何裝飾器做到這一點? –

+0

因爲'__new__'是特殊的。它自動是一個靜態方法,請參閱我在答案中鏈接的文檔。 –

+0

'__new__'是雙重特別。它本可以是一種分類方法。 (''float .__ new __(cls,..)'')傳遞'cls'時不帶'super()'調用父'__new__'的能力可能是[爲什麼'__new__'不是類方法] (http://stackoverflow.com/questions/9092072/why-isnt-new-in-python-new-style-classes-a-class-method)。 – jfs

0

一些背景知識來回答這個問題:

  1. 只有object.__new__()可以創建一個新instances類型的對象,這 類型的對象不能被繼承。
  2. 一個實例具有type,其可傳遞的類型名稱 cls__new__(cls)作爲第一個參數進行分配。 class關鍵詞creats 另一種對象:類(又名類型),這些類型的對象 可以被分類。

現在,返回到你的榜樣,什麼

float.__new__(cls, argument) 

基本上不使用object.__new__(cls)創建一個新的實例(float.__base__object), 分配(在這種情況下inch)類型cls到它,並且還在float.__new__中定義了argument

所以這並不奇怪,當cls不是floatinch它會工作:類/類型已經由class inch(float)創建的,你只是這個分配類型的新實例。