2016-02-23 46 views
5

Perché hasattr afferma che l'istanza non ha un attributo foo?L'hasattr di Python a volte restituisce risultati errati

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

mi aspettavo:

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

risposta

11

L'implementazione python2 di hasattr è abbastanza ingenuo, si cerca solo di accedere a tale attributo e vedere se solleva un'eccezione oppure no.

Sfortunatamente, ciò significa che eventuali eccezioni non gestite all'interno delle proprietà verranno inghiottite e gli errori in tale codice potrebbero andare persi. Per aggiungere la beffa al danno, quando hasattr mangia l'eccezione, verrà restituita anche una risposta errata (qui l'attributo a.fooè, quindi il risultato dovrebbe essere restituito True se necessario).

In python3.2 +, è stato corretto il comportamento:

hasattr(object, name)

Gli argomenti sono un oggetto e una stringa. Il risultato è True se la stringa è il nome di uno degli attributi dell'oggetto, False in caso contrario. (Questo viene implementato chiamando getattr(object, name) e vedere se si solleva un AttributeError o no.)

La correzione è here, ma purtroppo che il cambiamento non ha backport.

Se il comportamento di python2 causa problemi, considerare di evitare l'uso di hasattr; puoi invece provare/eccetto lo getattr, rilevando solo l'eccezione AttributeError e lasciando che altri aumentino.

+4

Nonostante la citazione dai documenti Python, il comportamento di 'hasattr' può ancora essere considerato strano. È vero che le eccezioni arbitrarie all'interno di una proprietà non causano più l'attributo da considerare assente (ma piuttosto vengono sollevate direttamente nella faccia del chiamante), ma se un "AttributeError" proviene da qualche parte all'interno della proprietà, il risultato di 'hasattr' sarà comunque essere 'False'. Questo potrebbe non essere intenzionale. (O può, così una proprietà può determinare se vuole essere "lì"). In ogni caso, l'esecuzione della proprietà suona male per me in primo luogo, considerando gli effetti collaterali ecc. –

+0

Non c'è un modo veramente diretto per determinare se un attributo 'AttributeError' è stato sollevato dall'attributo - ottenere la macchina stessa, o dal codice in una proprietà. – kindall