2011-07-31 77 views
8

我正在實現一個簡單的類來表示一個2D矢量。這裏的是相關的位:Python奇怪的錯誤:「TypeError:'NoneType'對象不可調用」

class Vector: 
    def __init__(self, x, y): 
    self.vec_repr = x, y 

    def __add__(self, other): 
    new_x = self.x + other.x 
    new_y = self.y + other.y 
    return Vector(new_x, new_y) 

    def __getattr__(self, name): 
    if name == "x": 
     return self.vec_repr[0] 
    elif name == "y": 
     return self.vec_repr[1] 

後來,我有這樣的:

a = Vector(1, 1) 
b = Vector(2, 2) 
a + b 

我得到TypeError: 'NoneType' object is not callable。這特別奇怪,因爲錯誤沒有被標記爲在任何特定的行上,所以我不知道在哪裏看!

非常奇怪,所以我做了一些實驗,發現它發生在行a+b。此外,當我重新班級如下:

​​

錯誤消失!

我看到有很多類似這樣的錯誤的問題 - 所有似乎都涉及到某個函數名被某個變量覆蓋的地方,但是我不知道這是怎麼回事!

至於另一條線索,當我改變的__getattr__()默認返回類型別的東西 - 海峽,例如 - 錯誤搖身一變TypeError: 'str' object is not callable

任何想法,這是怎麼回事?有沒有我不明白的__getattr__()的一些行爲?

回答

11

問題是您的__getattr__不會爲xy以外的屬性返回任何內容,也不會引發AttributeError。因此,當__add__方法查找時,__getattr__返回None,因此您的錯誤。

您可以通過爲其他屬性設置__getattr__返回值來解決此問題。實際上,您必須確保__getattr__針對所有未處理的屬性從其超類中調用該方法。但真的__getattr__是在這裏使用的錯誤的東西。它應該謹慎使用,並且當沒有更明顯的,更高級別的解決方案可用時。例如,__getattr__對於動態調度是必不可少的。但在你的情況下,xy值是衆所周知的,並且在代碼運行之前已經很好地定義了。

正確的解決方案是使xy屬性,而不是執行__getattr__根本。

@property 
def x(self): 
    return self.vec_repr[0] 

@property 
def y(self): 
    return self.vec_repr[1] 
+0

和公正的全貌,它試圖調用'__coerce__' –

+0

@yi_H我不熟悉'__coerce__',但我能猜出它會做什麼,以及爲什麼它會被稱爲! –

+0

哦。哇謝謝。我認爲它在__getattr __()時沒有找到其他地方的屬性。好吧,這非常令人尷尬。 – Slubb