views:

3883

answers:

6

Is there a way in Python to determine if an object has some attribute? For example:

>>> 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'

How can you tell if a has the attribute property before using it?

+32  A: 

Try hasattr():

if hasattr(a, 'property'):
    a.property

EDIT: See zweiterlinde below, who offers good advice about asking forgiveness! A very pythonic approach!

The general practice in python is that, if the property is likely to be there most of the time, simply call it and either let the exception propagate, or trap it with a try/except block. This will likely be faster than hasattr. If the property is likely to not be there most of the time, or you're not sure, using hasattr will probably be faster than repeatedly falling into an exception block.

Jarret Hardie
+4  A: 

I think what you are looking for is hasattr. However, I'd recommend something like this if you want to detect python properties-

try:
    getattr(someObject, 'someProperty')         
except AttributeError:
    print "Doesn't exist"
else
    print "Exists"

The disadvantage here is that attribute errors in the properties __get__ code are also caught.

Otherwise, do-

if hasattr(someObject, 'someProp'):
    #Access someProp/ set someProp
    pass

Docs:http://docs.python.org/library/functions.html
Warning:
The reason for my recommendation is that hasattr doesn't detect properties.
Link:http://mail.python.org/pipermail/python-dev/2005-December/058498.html

batbrat
so, your advice is don't you buil-in - implement it!
SilentGhost
Well, not exactly, don't use the built-in IFF you want to detect properties. Otherwise hasattr is perfectly good.
batbrat
+1  A: 

According to pydoc, hasattr(obj, prop) simply calls getattr(obj, prop) and catches exceptions. So, it is just as valid to wrap the attribute access with a try statement and catch AttributeError as it is to use hasattr() beforehand.

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value
Jordan Lewis
+24  A: 

As Jarret Hardie answered, hasattr will do the trick. I would like to add, though, that many in the Python community recommend a strategy of "easier to ask for forgiveness than permission" (EAFP) rather than "look before you leap" (LBYL). See these references:

http://mail.python.org/pipermail/python-list/2003-May/205182.html
http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#id47

ie:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

... is preferred to:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()
zweiterlinde
But how do you check that it was the a.property that caused AttributeError, and not something in doStuff()? It seems you don't. I think it is really easier to ask for forgiveness, but many times, it's also incorrect.
jpalecek
EAFP seems ... insane. HasAttr telegraphs to future maintance programmers that you are checking for a particular attribute. Getting an exception tells future programmers nothing and could lead someone down the rabbit hole.
e5
+1  A: 

Depending on the situation you can check with isinstance what kind of object you have, and then use the corresponding attributes. With the introduction of abstract base classes in Python 2.6/3.0 this approach has also become much more powerful (basically ABCs allow for a more sophisticated way of duck typing).

One situation were this is useful would be if two different objects have an attribute with the same name, but with different meaning. Using only hasattr might then lead to strange errors.

One nice example is the distinction between iterators and iterables (see this question). The __iter__ methods in an iterator and an iterable have the same name but are semantically quite different! So hasattr is useless, but isinstance together with ABC's provides a clean solution.

However, I agree that in most situations the hasattr approach (described in other answers) is the most appropriate solution.

nikow
+4  A: 

hasattr() and catching AttributeError are two good options. If you really just want the value of the attribute with a default if it isn't there, the most concise option is just to use getattr():

getattr(a, 'property', 'default value')
Carl Meyer