if hasattr(obj, 'attribute'):
# do somthing
vs
try:
# access obj.attribute
except AttributeError, e:
# deal with AttributeError
Which should be preferred and why?
if hasattr(obj, 'attribute'):
# do somthing
vs
try:
# access obj.attribute
except AttributeError, e:
# deal with AttributeError
Which should be preferred and why?
If not having the attribute is not an error condition, the exception handling variant has a problem: it would catch also AttributeErrors that might come internally when accessing obj.attribute (for instance because attribute is a property so that accessing it calls some code).
If it's just one attribute you're testing, I'd say use
hasattr
. However, if you're doing several accesses to attributes which may or may not exist then using atry
block may save you some typing.This subject was covered in the EuroPython 2016 talk Writing faster Python by Sebastian Witowski. Here's a reproduction of his slide with the performance summary. He also uses the terminology look before you leap in this discussion, worth mentioning here to tag that keyword.
3 PERMISSIONS OR FORGIVENESS?
At least when it is up to just what's going on in the program, leaving out the human part of readability, etc. (which is actually most of the time more imortant than performance (at least in this case - with that performance span), as Roee Adler and others pointed out).
Nevertheless looking at it from that perspective, it then becomes a matter of choosing between
and
since
hasattr
just uses the first case to determine the result. Food for thought ;-)Any benches that illustrate difference in performance?
timeit it's your friend
There is a third, and often better, alternative:
Advantages:
getattr
does not have the bad exception-swallowing behavior pointed out by Martin Geiser - in old Pythons,hasattr
will even swallow aKeyboardInterrupt
.The normal reason you're checking if the object has an attribute is so that you can use the attribute, and this naturally leads in to it.
The attribute is read off atomically, and is safe from other threads changing the object. (Though, if this is a major concern you might want to consider locking the object before accessing it.)
It's shorter than
try/finally
and often shorter thanhasattr
.A broad
except AttributeError
block can catch otherAttributeErrors
than the one you're expecting, which can lead to confusing behaviour.Accessing an attribute is slower than accessing a local variable (especially if it's not a plain instance attribute). (Though, to be honest, micro-optimization in Python is often a fool's errand.)
One thing to be careful of is if you care about the case where
obj.attribute
is set to None, you'll need to use a different sentinel value.