2016-02-23 62 views
5

爲什麼hasattr說實例沒有foo屬性?Python的hasattr有時會返回不正確的結果

>>> class A(object): 
...  @property 
...  def foo(self): 
...   ErrorErrorError 
... 
>>> a = A() 
>>> hasattr(a, 'foo') 
False 

我預計:

>>> hasattr(a, 'foo') 
NameError: name 'ErrorErrorError' is not defined` 

回答

11

hasattr的python2實現是相當幼稚的,它只是試圖訪問該屬性,看看它是否引發異常或沒有。

不幸的是,這意味着屬性中的任何未處理的異常都會被吞下,並且該代碼中的錯誤可能會丟失。爲了增加傷害,當有異常時,它也會返回一個不正確的答案(這裏的屬性a.foo存在,所以如果有的話,結果應該返回True)。

在python3.2 +,行爲已被校正:

hasattr(object, name)

的參數是一個對象和一個字符串。如果字符串是對象屬性之一的名稱,則結果爲True,如果不是,則爲False。 (這是通過調用getattr(object, name),看它是否引發一個AttributeError或不執行。)

解決方法是here,但不幸的是這種改變並沒有反向移植。

如果python2行爲給您造成麻煩,請考慮避免使用hasattr;相反,您可以嘗試使用/除getattr外,僅捕獲AttributeError例外情況,並讓其他任何人未處理。

+4

儘管有來自Python文檔的引用,'hasattr'行爲仍然可能被認爲是奇怪的。確實,屬性內部的任意異常不再導致該屬性被認爲是不存在的(而是在調用者的臉上被引發),但是如果AttributeError來自屬性內的某個地方,hasattr的結果仍然會是'假'。這可能不是故意的。 (或者它可能,所以一個屬性可以確定它是否想要「在那裏」。)在任何情況下,首先執行屬性聽起來都是錯誤的,考慮到副作用等。 –

+0

沒有真正的直接方法以確定屬性獲取機制本身或屬性中的代碼是否引發了'AttributeError'。 – kindall