Given the following class (with a buggy property) then what is the best foolproof way of checking that the bar
property exists?
class Foo(object):
@property
def bar(self):
raise AttributeError('unforeseen attribute error!')
Both hasattr
and getattr
fail and only dir
works:
foo = Foo()
print hasattr(foo, 'bar')
# False
try:
getattr(foo, 'bar')
print True
except AttributeError as e:
print False
# False
print 'bar' in dir(foo)
# True
The best all round solution I can think of is:
def robust_hasattr(obj, attr):
return hasattr(obj, attr) or attr in dir(obj)
Is there a better way?
If you have a buggy property, fix the bug. If raising AttributeError
is a bug, then make the property not do that. Raising that exception is the way to signal that you should not be using that attribute.
Using dir()
can be a work-around, but it is not foolproof, as dir()
is a debugging aid that can both omit information and can be overridden by the object.__dir__
hook (giving your code another vector to introduce bugs). Then there is the possibility of a buggy object.__getattr__
hook, a buggy object.__getattribute__
hook, or even descriptors on the metaclass, all of which would not be detectable by using dir()
.
Since you are specifically looking for a property, look for the same attribute on the class of your object:
hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)
For your specific case, the above returns True:
>>> class Foo(object):
... @property
... def bar(self):
... raise AttributeError('unforeseen attribute error!')
...
>>> foo = Foo()
>>> hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)
True
because there indeed is such a property
object on the class.