如何可靠地检查 Python 属性 是否存在?

How to robustly check a Python property exists?

给定以下 class(有一个 buggy 属性)那么检查 bar 属性 是否存在的最佳万无一失的方法是什么?

class Foo(object):
    @property
    def bar(self):
        raise AttributeError('unforeseen attribute error!')

hasattrgetattr 都失败了,只有 dir 有效:

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

我能想到的最好的全面解决方案是:

def robust_hasattr(obj, attr):
    return hasattr(obj, attr) or attr in dir(obj)

有没有更好的方法?

如果您有错误 属性,修复错误。如果提高 AttributeError 是一个错误,那么让 属性 不这样做。引发该异常是 表示您不应使用该属性的方式。

使用 dir() 可能是一种解决方法,但它是 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,甚至是元 class 上的描述符,所有这些都无法通过使用 dir().

由于您专门寻找 属性,请在对象的 class 上寻找相同的属性:

hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)

对于您的具体情况,上述 returns 正确:

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

因为class上确实有这样一个property对象。

根据 Python 的规则,bar 属性 不存在 。如果访问属性的尝试没有引发异常,则认为对象具有属性。

如果您想对属性是否存在使用不同的概念,您可以自己实现该概念。例如,要检查实例字典中是否存在对应于 bar 或 class 字典之一的条目:

for obj in (foo,) + type(foo).__mro__:
    if 'bar' in obj.__dict__:
        print "It's there."
        break
else:
    print "Didn't find it."