3

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

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

两者都hasattr失败getattr并且仅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)

有没有更好的办法?

4

2 回答 2

7

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

Usingdir()可以是一种变通方法,但它不是万无一失的,因为它dir()是一种调试辅助工具,既可以省略信息,也可以被object.__dir__钩子覆盖(为您的代码提供另一个向量以引入错误)。然后有可能在元类上存在错误object.__getattr__钩子错误object.__getattribute__钩子甚至描述符,所有这些都无法通过使用dir().

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

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

对于您的具体情况,以上返回 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

因为类上确实有这样的property对象。

于 2016-05-19T08:22:44.723 回答
3

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

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

for obj in (foo,) + type(foo).__mro__:
    if 'bar' in obj.__dict__:
        print "It's there."
        break
else:
    print "Didn't find it."
于 2016-05-19T08:23:07.907 回答