Come sapere se un oggetto ha un attributo in Python
-
03-07-2019 - |
Domanda
C'è un modo in Python per determinare se un oggetto ha qualche attributo? Ad esempio:
>>> a = SomeClass()
>>> a.someProperty = value
>>> a.property
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'
Come puoi sapere se a
ha l'attributo proprietà
prima di usarlo?
Soluzione
Prova hasattr ()
:
if hasattr(a, 'property'):
a.property
EDIT: vedi la risposta di zweiterlinde , che offre buoni consigli su come chiedere perdono! Un approccio molto pitonico!
La pratica generale in Python è che, se è probabile che la proprietà sia presente per la maggior parte del tempo, è sufficiente chiamarla e lasciare che l'eccezione si propaghi oppure intercettarla con un blocco try / tranne. Questo sarà probabilmente più veloce di hasattr
. Se è probabile che la proprietà non ci sia la maggior parte del tempo, o non sei sicuro, l'utilizzo di hasattr
sarà probabilmente più veloce rispetto alla caduta ripetuta in un blocco di eccezioni.
Altri suggerimenti
Come Jarret Hardie ha risposto, hasattr
farà il trucco. Vorrei aggiungere, tuttavia, che molti nella comunità di Python raccomandano una strategia di "più facile chiedere perdono che permesso" (EAFP) anziché "guardare prima di saltare" (LBYL). Vedi questi riferimenti:
EAFP vs LBYL (era Re: un po 'deluso finora)
EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python
vale a dire:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
... è preferito a:
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
Puoi usare hasattr ()
o catturare AttributeError
, ma se vuoi davvero il valore dell'attributo con un valore predefinito se non c'è, il migliore l'opzione è solo per usare getattr ()
:
getattr(a, 'property', 'default value')
Penso che quello che stai cercando sia hasattr . Tuttavia, consiglierei qualcosa del genere se si desidera rilevare proprietà python -
try:
getattr(someObject, 'someProperty')
except AttributeError:
print "Doesn't exist"
else
print "Exists"
Lo svantaggio qui è che vengono catturati anche gli errori di attributo nel codice __get__
delle proprietà.
Altrimenti, do-
if hasattr(someObject, 'someProp'):
#Access someProp/ set someProp
pass
Documenti: http://docs.python.org/library/functions.html
Attenzione:
Il motivo della mia raccomandazione è che hasattr non rileva le proprietà.
Link: http://mail.python.org/pipermail/python -dev / 2005-dicembre / 058498.html
Secondo pydoc, hasattr (obj, prop) chiama semplicemente getattr (obj, prop) e rileva delle eccezioni. Quindi, è altrettanto valido racchiudere l'accesso all'attributo con un'istruzione try e catturare AttributeError come usare in anticipo hasattr ().
a = SomeClass()
try:
return a.fake_prop
except AttributeError:
return default_value
Vorrei suggerire di evitare questo:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
L'utente @jpalecek l'ha menzionato: se si verifica un AttributeError
all'interno di doStuff ()
, ci si perde.
Forse questo approccio è migliore:
try:
val = a.property
except AttributeError:
otherStuff()
else:
doStuff(val)
A seconda della situazione, puoi verificare con isinstance
che tipo di oggetto hai e quindi utilizzare gli attributi corrispondenti. Con l'introduzione di classi di base astratte in Python 2.6 / 3.0 questo approccio ha diventano anche molto più potenti (in pratica gli ABC consentono un modo più sofisticato di scrivere l'anatra).
Una situazione in cui ciò sarebbe utile sarebbe se due oggetti diversi hanno un attributo con lo stesso nome, ma con significato diverso. L'uso di hasattr
potrebbe quindi portare a strani errori.
Un bell'esempio è la distinzione tra iteratori e iterabili (vedi questa domanda). I metodi __iter__
in un iteratore e in un iterabile hanno lo stesso nome ma sono semanticamente abbastanza diversi! Quindi hasattr
è inutile, ma isinstance
insieme a ABC fornisce una soluzione pulita.
Tuttavia, sono d'accordo che nella maggior parte dei casi l'approccio hasattr
(descritto in altre risposte) è la soluzione più appropriata.
Spero che ti aspetti hasattr (), ma cerca di evitare hasattr () e preferisci getattr (). getattr () è più veloce di hasattr ()
utilizzando hasattr ():
if hasattr(a, 'property'):
print a.property
stesso qui sto usando getattr per ottenere proprietà se non c'è proprietà che non ne restituisce nessuna
property = getattr(a,"property",None)
if property:
print property
MODIFICA : questo approccio presenta serie limitazioni. Dovrebbe funzionare se l'oggetto è iterabile . Si prega di controllare i commenti qui sotto.
Se stai usando Python 3.6 o superiore come me, c'è una comoda alternativa per verificare se un oggetto ha un attributo particolare:
if 'attr1' in obj1:
print("attr1 = {}".format(obj1["attr1"]))
Tuttavia, non sono sicuro di quale sia l'approccio migliore in questo momento. usando hasattr ()
, usando getattr ()
o usando in
. I commenti sono ben accetti.
Ecco un approccio molto intuitivo:
if 'property' in dir(a):
a.property
Puoi verificare se oggetto
contiene attributi usando il metodo incorporato hasattr
.
Ad esempio, se l'oggetto è a
e si desidera verificare l'attributo stuff
>>> class a:
... stuff = "something"
...
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False
La stessa firma del metodo è hasattr (oggetto, nome) - > bool
che significa se oggetto
ha attributo che viene passato al secondo argomento in hasattr
di quello che dà booleano True
o False
in base alla presenza dell'attributo name
nell'oggetto.
Questo è super semplice, basta usare dir(
oggetto )
Questo restituirà un elenco di tutte le funzioni e gli attributi disponibili dell'oggetto.