2383

How do I check if an object has some attribute? For example:

>>> a = SomeClass()
>>> a.property
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'

How do I tell if a has the attribute property before using it?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Lucas Gabriel Sánchez
  • 40,116
  • 20
  • 56
  • 83
  • When you say *"tell if a has the attribute property before using it?"* do you want a function returning a boolean (like `hasattr()` returns) or is it ok to throw an `AttributeError` exception? – smci Feb 28 '22 at 04:04
  • 4
    Also, don't actually name your attribute 'property' , because Python has [`property` decorator and builtin](https://docs.python.org/3/howto/descriptor.html#properties) too, and those are slightly different than normal attributes/methods. – smci Feb 28 '22 at 04:07

16 Answers16

3347

Try hasattr():

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

See zweiterlinde's answer 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.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Jarret Hardie
  • 95,172
  • 10
  • 132
  • 126
  • 28
    Seems to be working for checking for functions in namespace as well, e.g.: `import string hasattr(string, "lower")` – riviera Apr 08 '11 at 12:54
  • 22
    `hasattr` is exactly the same as using `try`/`except AttributeError`: the docstring of hasattr (in Python 2.7) says that it uses getattr hand catches exceptions. – Jeff Tratner Apr 27 '12 at 03:04
  • 11
    @JeffTratner: `hasattr` is unfortunately not *exactly* the same as a `try: ... except AttributeError:` in Python 2.x since `hasattr` will **catch all exception**. Please see [my answer](http://stackoverflow.com/a/16186050/110204) for an example and a simple workaround. – Martin Geisler Apr 24 '13 at 07:44
  • 2
    hasattr does not work if your object is a 'dict'. Use in operator or haskey method in those cases. – AnandShiva Apr 04 '21 at 12:13
  • 3
    can it be done for attribute for `self`? like `if not hasattr(self, 'property')` inside the `__init__()` of the object creation – alper Sep 14 '21 at 03:51
  • @alper yes, for example `hasattr(self, 'config')` – nck Nov 14 '22 at 10:39
819

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:

EAFP vs LBYL (was Re: A little disappointed so far)
EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python

ie:

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

... is preferred to:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()
Gfy
  • 8,173
  • 3
  • 26
  • 46
zweiterlinde
  • 14,557
  • 2
  • 27
  • 32
  • 352
    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 Apr 14 '09 at 13:22
  • 380
    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. – Ethan Heilman Oct 14 '10 at 18:54
  • 89
    @e5: you have a fair point in this case, but in many cases EAFP is the only correct option. For example, if you check the existence of a file and then open it, expecting that it will definitely exist, your code is incorrect: the file may be deleted or renamed between the check and the use. This is called a TOCTOU error (Time-Of-Check-To-Time-Of-Use) and besides causing crashes can also be a source of security vulnerabilities. – Max Jun 01 '11 at 13:08
  • 23
    @EthanHeilman it's only insane when there is ambiguity in the source of the exception, which can be avoided with good design in most cases. Well-layered structuring of logic within try / except / finally generally makes for more robust (less programmer error prone) logic than littering the code with preemptive if-checks for each piece of consuming code. Makes errors very explicit also, and allows consuming programmers the option of dealing with them directly. – Peter M. Elias Jan 02 '13 at 16:23
  • 80
    Most of the ambiguity complaints here are simply because the sample code is poorly structured. The only thing inside the `try:` should be the attempted attribute access; there's no reason to wrap the execution of `doStuff` as well. There still is some potential for ambiguity though: if `property` is a computed property instead of a plain attribute, its implementation could raise `AttributeError` internally. This is why in almost all real situations like this, `getattr` is preferable to either `hasattr` or catching `AttributeError`. – Carl Meyer Sep 24 '13 at 20:21
  • 4
    What if you only need to do something if an attribute exists, and otherwise do nothing? Would you do `try` - `except: pass` ? It is inefficient, but also bad style, because it isn't an actual exception or error you are dealing with here, it is the expected flow of the program for objects without a certain attribute. – Ataxias Jan 29 '21 at 08:02
  • There's nothing wrong with `try: except: pass`. Just put the code you want to execute if the attribute exists (and there is no exception) in the following `else` clause. It is not bad style. – rooms Feb 10 '23 at 12:36
653

You can use hasattr() or catch AttributeError, but if you really just want the value of the attribute with a default if it isn't there, the best option is just to use getattr():

getattr(a, 'property', 'default value')
Georgy
  • 12,464
  • 7
  • 65
  • 73
Carl Meyer
  • 122,012
  • 20
  • 106
  • 116
  • 19
    This solves both aforementioned problems: a) The ambiguity of the source of a possible AttributeError, b) Preserving the EAFP approach. – Peter M. Elias Jan 02 '13 at 16:17
  • 10
    It's also 25% of the lines of code. Surely this has to be the best solution. – fatuhoku Sep 24 '13 at 11:36
  • 23
    This is the best solution "if you really just want the value of the attribute with a default." Although I believe this is what many people actually want when they say they want to detect whether an attribute is present, the OP actually asked for the latter, so it's reasonable for the direct answers to that question (hasattr, AttributeError) to be listed higher. – Carl Meyer Dec 01 '15 at 05:48
  • Upvoted for mentioning "default property". There have been times I needed this, but forgot about it! – Vexen Crabtree Jun 24 '21 at 11:56
  • It's much better than the accepted answer as for me in most cases, because hasattr usually used to check if attr exists and then check its value to avoid exception, and this helps to check value directly without 'if hasattr and check value' – Gryu Dec 09 '22 at 09:55
56

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
  • 5,155
  • 3
  • 32
  • 38
  • 4
    `hasattr` detects properties in general just fine. It's just that it treats raising an exception in the `property`-wrapped function as meaning no such attribute exists; the linked Python mailing list post is about a property that raises an exception when you attempt to access it. For all practical purposes, said attribute doesn't exist, because it will never produce a value. Also, `hasattr` only suppresses exceptions in general on Py 3.1 and earlier; in 3.2+, it only suppresses (replacing with `False` return) `AttributeError`. – ShadowRanger Apr 25 '18 at 19:32
41

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
  • 16,900
  • 4
  • 29
  • 46
  • 3
    Well hasattr actually *may be* optimized. E.g. with pypy. – odinho - Velmont Aug 18 '11 at 17:37
  • 7
    +1. This is even *safer* than using `hasattr` when `SomeClass` overrides `__getattr__` since `hasattr` will catch **all** exceptions in Python 2.x, not just `AttributeError` like you would expect. This was fixed in Python 3.2 — please see [my other answer](http://stackoverflow.com/a/16186050/110204) for a simple workaround. – Martin Geisler Apr 24 '13 at 07:47
36

I would like to suggest avoid this:

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

The user @jpalecek mentioned it: If an AttributeError occurs inside doStuff(), you are lost.

Maybe this approach is better:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)
Maico
  • 719
  • 7
  • 11
23

hasattr() is the right answer. What I want to add is that hasattr() can be used well in conjunction with assert (to avoid unnecessary if statements and make the code more readable):

assert hasattr(a, 'property'), 'object lacks property' 
print(a.property)

In case that the property is missing, the program will exit with an AssertionError and printing out the provided error message (object lacks property in this case).

As stated in another answer on SO:

Asserts should be used to test conditions that should never happen. The purpose is to crash early in the case of a corrupt program state.

Often this is the case when a property is missing and then assert is very appropriate.

F.M.F.
  • 1,929
  • 3
  • 23
  • 42
  • 2
    This is helpfull but may not be always the case. Perhaps I wanted to test if the object has a property and then add it for the first time, or maybe I have to run different code for objects with that property. When the code can't continue the assert may be fine. But again, is not always the case. The important thing is the use of `hasattr` not the surrounding code. – Lucas Gabriel Sánchez May 28 '20 at 12:19
22

For objects other than dictonary:

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

For dictionary, hasattr() will not work.

Many people are telling to use has_key() for dictionary, but it is depreciated. So for dictionary, you have to use has_attr()

if a.has_attr('property'):
    a['property']
 

Or you can also use

if 'property' in a:
Shashi
  • 565
  • 5
  • 8
20

EDIT:This approach has serious limitation. It should work if the object is an iterable one. Please check the comments below.

If you are using Python 3.6 or higher like me there is a convenient alternative to check whether an object has a particular attribute:

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))

However, I'm not sure which is the best approach right now. using hasattr(), using getattr() or using in. Comments are welcome.

nayak
  • 2,807
  • 1
  • 17
  • 19
  • 8
    `in` keyword works for checking iterable types. For example, `'foo' in None` throws the error `TypeError: argument of type 'NoneType' is not iterable`. The fix is to check if the type is iterable before using `in`. After correcting for edge cases like non-iterable type, you're probably better off using `hasattr()` because it's designed to handle the edge cases. – Seth Difley Oct 05 '17 at 13:06
  • 5
    This has nothing to do with attribute access. I have no idea how it got upvoted. The only similarity it has to attribute access is if you are using `dict` as a "lightweight object", similar to the design of JavaScript objects, but most normal classes will not support this in general (getting a variant on the error mentioned by @SethDifley). – ShadowRanger Apr 25 '18 at 19:37
18

Hope you expecting hasattr(), but try to avoid hasattr() and please prefer getattr(). getattr() is faster than hasattr()

using hasattr():

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

same here i am using getattr to get property if there is no property it return none

   property = getattr(a,"property",None)
    if property:
        print property
Janarthanan Ramu
  • 1,331
  • 16
  • 17
  • `getattr() is faster than hasattr()`, could you please comment on this? Why faster? – Groosha Jul 25 '20 at 11:20
  • 3
    @Groosha There are many things, to make it simple hasattr() internally have to call getattr() to perform their operation, so instead calling multiple method we can use direct getattr() check this https://docs.python.org/3/library/functions.html#hasattr – Janarthanan Ramu Jul 27 '20 at 18:14
  • 3
    But if the property does exist and its value is `False` you can end up with a false positive. – user9538 Jul 14 '21 at 00:02
18

Here's a very intuitive approach :

if 'property' in dir(a):
    a.property

If a is a dictionary, you can check normally

if 'property' in a:
    a.property
Alec
  • 8,529
  • 8
  • 37
  • 63
  • It's good to know that this is possible, but I suggest against using dir() and instead using hasattr(). The function dir() will not find meta-class supplied attributes. For more, check https://stackoverflow.com/questions/17723569/whats-the-difference-between-hasattr-and-attribute-in-dir. – MattSt Aug 12 '22 at 07:27
17

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.

Community
  • 1
  • 1
nikow
  • 21,190
  • 7
  • 49
  • 70
6

You can use hasattr() to check if object or class has an attribute in Python.

For example, there is Person class as shown below:

class Person:
    greeting = "Hello"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def test(self):
        print("Test")

Then, you can use hasattr() for object as shown below:

obj = Person("John", 27)
obj.gender = "Male"
print("greeting:", hasattr(obj, 'greeting'))
print("name:", hasattr(obj, 'name'))
print("age:", hasattr(obj, 'age'))
print("gender:", hasattr(obj, 'gender'))
print("test:", hasattr(obj, 'test'))
print("__init__:", hasattr(obj, '__init__'))
print("__str__:", hasattr(obj, '__str__'))
print("__module__:", hasattr(obj, '__module__'))

Output:

greeting: True
name: True
age: True
gender: True
test: True
__init__: True
__str__: True
__module__: True

And, you can also use hasattr() directly for class name as shown below:

print("greeting:", hasattr(Person, 'greeting'))
print("name:", hasattr(Person, 'name'))
print("age:", hasattr(Person, 'age'))
print("gender:", hasattr(Person, 'gender'))
print("test:", hasattr(Person, 'test'))
print("__init__:", hasattr(Person, '__init__'))
print("__str__:", hasattr(Person, '__str__'))
print("__module__:", hasattr(Person, '__module__'))

Output:

greeting: True
name: False
age: False
gender: False
test: True
__init__: True
__str__: True
__module__: True
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
4

This is super simple, just use dir(object)
This will return a list of every available function and attribute of the object.

3

You can check whether object contains attribute by using hasattr builtin method.

For an instance if your object is a and you want to check for attribute stuff

>>> class a:
...     stuff = "something"
... 
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False

The method signature itself is hasattr(object, name) -> bool which mean if object has attribute which is passed to second argument in hasattr than it gives boolean True or False according to the presence of name attribute in object.

Devang Padhiyar
  • 3,427
  • 2
  • 22
  • 42
0

Another possible option, but it depends if what you mean by before:

undefined = object()

class Widget:

    def __init__(self):
        self.bar = 1

    def zoom(self):
        print("zoom!")

a = Widget()

bar = getattr(a, "bar", undefined)
if bar is not undefined:
    print("bar:%s" % (bar))

foo = getattr(a, "foo", undefined)
if foo is not undefined:
    print("foo:%s" % (foo))

zoom = getattr(a, "zoom", undefined)
if zoom is not undefined:
    zoom()

output:

bar:1
zoom!

This allows you to even check for None-valued attributes.

But! Be very careful you don't accidentally instantiate and compare undefined multiple places because the is will never work in that case.

Update:

because of what I was warning about in the above paragraph, having multiple undefineds that never match, I have recently slightly modified this pattern:

undefined = NotImplemented

NotImplemented, not to be confused with NotImplementedError, is a built-in: it semi-matches the intent of a JS undefined and you can reuse its definition everywhere and it will always match. The drawbacks is that it is "truthy" in booleans and it can look weird in logs and stack traces (but you quickly get over it when you know it only appears in this context).

JL Peyret
  • 10,917
  • 2
  • 54
  • 73