Since everything in Python is an object and objects have attributes (fields and methods), it's natural to write programs that can inspect what kind of attributes an object has. For example, a Python program could open a socket on the server and it accepts Python scripts sent over the network from a client machine. Upon receiving a new script, the server-side Python program can inspect or more precisely introspect objects, modules, and functions in the new script to decide how to perform the function, log the result, and various useful tasks.
hasattr vs. try-except
There're two ways to check if a Python object has an attribute or not. The first way is to call the built-in function hasattr(object, name)
, which returns True
if the string name
is the name of one of the object
's attributes, False
if not. The second way is to try
to access an attribute in an object
and perform some other function if an AttributeError
was raised.
[python]
>>> hasattr('abc', 'upper')
True
>>> hasattr('abc', 'lower')
True
>>> hasattr('abc', 'convert')
False
[/python]
And:
[python]
>>> try:
... 'abc'.upper()
... except AttributeError:
... print("abc does not have attribute 'upper'")
...
'ABC'
>>> try:
... 'abc'.convert()
... except AttributeError:
... print("abc does not have attribute 'convert'")
...
abc does not have attribute 'convert'
[/python]
What's the difference between these two styles? hasattr
is often referred as a Python programming style called "Look Before You Leap" (LBYL) because you check whether an object has an attribute or not before you access it. While try-except
is referred as "Easier to Ask for Forgiveness than Permission" (EAFP) because you try
the attribute access first and ask for forgiveness in the except
block instead of asking for permission like hasattr
.
Which way is better, then? Well, both doctrines have loyal supporters and both styles seem to be well-versed to deal with any real-world programming challenge. Sometimes, it makes sense to use LBYL if you want to make sure an attribute definitely exists and stop execution if it doesn't. For example, you know for certain at a point in the program that a passed-in object
should have a valid file pointer attribute on which the following code can work. On the other hand, it also makes sense to use EAFP if you know an attribute might not exist at some point during the program's execution. For example, a music player could not guarantee a MP3 file is always on-disk at the same location, because it might be deleted, modified, or moved by the user at any time. In this case, the music player can try
to access the MP3 file first and notify the user that the file does not exist in an except
block.
hasattr vs __dict__
Although hasattr
is a built-in function that is designed to check if an attribute exists in an object, sometimes it might be more accurate to check an object's __dict__
for an attribute's existence instead due to the fact that hasattr
does not care about the reason why an attribute's attached to an object while you may want to know why an attribute's attached to an object. For example, an attribute might be attached to an object due to its parent class instead of the object itself.
[python]
>>> class A(object):
... foo = 1
...
>>> class B(A):
... pass
...
>>> b = B()
>>> hasattr(b, 'foo')
True
>>> 'foo' in b.__dict__
False
[/python]
In the previous code, since class B
is a subclass of class A
, class B
also has the attribute "foo". However, because "foo" is inherited from A
, B.__dict__
does not contain it. Sometimes, it might be crucial to know whether an attribute comes from an object's class itself or from the objects' superclass.
Tips and Suggestions
hasattr
follows the duck-typing principle in Python:
When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.
So, most of the time you want to use
hasattr
to check if an attribute exists in an object.try-except
and__dict__
have their own use cases which are actually quite narrow compared tohasattr
. So, it is beneficial to keep these special use cases in the back of your head so that you will recognize them during coding and use the proper idioms accordingly.
Once you've learnt how to check if an object has an attribute in Python, checkout how to get an attribute from an object.