ChatGPT解决这个技术问题 Extra ChatGPT

How to know if an object has an attribute in Python

How do I determine 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 can you tell if a has the attribute property before using it?

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?
Also, don't actually name your attribute 'property' , because Python has property decorator and builtin too, and those are slightly different than normal attributes/methods.

N
Neuron

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.


Seems to be working for checking for functions in namespace as well, e.g.: import string hasattr(string, "lower")
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.
@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 for an example and a simple workaround.
hasattr does not work if your object is a 'dict'. Use in operator or haskey method in those cases.
can it be done for attribute for self? like if not hasattr(self, 'property') inside the __init__() of the object creation
G
Gfy

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()

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.
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: 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.
@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.
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.
G
Georgy

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

This solves both aforementioned problems: a) The ambiguity of the source of a possible AttributeError, b) Preserving the EAFP approach.
It's also 25% of the lines of code. Surely this has to be the best solution.
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.
Upvoted for mentioning "default property". There have been times I needed this, but forgot about it!
b
batbrat

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


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.
J
Jordan Lewis

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

Well hasattr actually may be optimized. E.g. with pypy.
+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 for a simple workaround.
M
Maico

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)

n
nayak

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.


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.
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).
F
F.M.F.

hasattr() is the right answer. What I want to add is that hasattr() can also 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.


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.
C
Community

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.


J
Janarthanan Ramu

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

getattr() is faster than hasattr(), could you please comment on this? Why faster?
@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 docs.python.org/3/library/functions.html#hasattr
But if the property does exist and its value is False you can end up with a false positive.
N
Neuron

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

For dict, use if 'property' in a:
A
Alec

Here's a very intuitive approach :

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

S
Sean Christians

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


D
Devang Padhiyar

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.


nit: hasattr() is a function, not a method. See here.
J
JL Peyret

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).