如何稳健地检查Python属性是否存在?

101*_*101 3 python attributes properties hasattr getattr

给定以下类(具有错误的属性),那么检查该bar属性是否存在的最佳方法是什么?

class Foo(object):
    @property
    def bar(self):
        raise AttributeError('unforeseen attribute error!')
Run Code Online (Sandbox Code Playgroud)

无论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
Run Code Online (Sandbox Code Playgroud)

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

def robust_hasattr(obj, attr):
    return hasattr(obj, attr) or attr in dir(obj)
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?

Mar*_*ers 6

如果您有越野车属性,请修复bug。如果提高AttributeError是一个错误,则使该属性不这样做。提高该异常信号,你不应该使用该属性的方式。

使用dir()可以解决,但不是万无一失的,因为dir()调试助手可以忽略信息,并且可以被object.__dir__钩子覆盖(为代码提供另一个引入错误的媒介)。然后可能会在元类上出现bug object.__getattr__钩子bug object.__getattribute__钩子甚至描述符,而使用都无法检测到所有这些钩子dir()

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

hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)
Run Code Online (Sandbox Code Playgroud)

对于您的特定情况,以上返回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
Run Code Online (Sandbox Code Playgroud)

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