Search code examples
pythonpropertiesattributesgetattrhasattr

How to robustly check a Python property exists?


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?


Solution

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