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?
From a practical point of view, in most languages using a conditional will always be consderably faster than handling an exception.
If you're wanting to handle the case of an attribute not existing somewhere outside of the current function, the exception is the better way to go. An indicator that you may want to be using an exception instead of a conditional is that the conditional merely sets a flag and aborts the current operation, and something elsewhere checks this flag and takes action based on that.
That said, as Rax Olgud points out, communication with others is one important attribute of code, and what you want to say by saying "this is an exceptional situation" rather than "this is is something I expect to happen" may be more important.
The first.
Shorter is better. Exceptions should be exceptional.
I'd suggest option 2. Option 1 has a race condition if some other thread is adding or removing the attribute.
Also python has an Idiom, that EAFP ('easier to ask forgiveness than permission') is better than LBYL ('look before you leap').
I almost always use
hasattr
: it's the correct choice for most cases.The problematic case is when a class overrides
__getattr__
:hasattr
will catch all exceptions instead of catching justAttributeError
like you expect. In other words, the code below will printb: False
even though it would be more appropriate to see aValueError
exception:The important error has thus disappeared. This has been fixed in Python 3.2 (issue9666) where
hasattr
now only catchesAttributeError
.An easy workaround is to write a utility function like this:
This let's
getattr
deal with the situation and it can then raise the appropriate exception.hasattr
internally and rapidly performs the same task as thetry/except
block: it's a very specific, optimized, one-task tool and thus should be preferred, when applicable, to the very general-purpose alternative.I would say it depends on whether your function may accept objects without the attribute by design, e.g. if you have two callers to the function, one providing an object with the attribute and the other providing an object without it.
If the only case where you'll get an object without the attribute is due to some error, I would recommend using the exceptions mechanism even though it may be slower, because I believe it is a cleaner design.
Bottom line: I think it's a design and readability issue rather than an efficiency issue.