如何检查一个对象是否有属性?

如何检查对象是否具有某些属性?例如:

>>> a = SomeClass()>>> a.propertyTraceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: SomeClass instance has no attribute 'property'

在使用之前,我如何判断a是否具有属性property

1288411 次浏览

尝试#0

if hasattr(a, 'property'):a.property

请看下面的zweiterlinde的回答,他提供了关于请求原谅的好建议!一个非常Pythonic的方法!

python的一般做法是,如果属性可能大部分时间都在那里,只需调用它并让异常传播,或者使用try/例外块捕获它。这可能比hasattr快。如果属性可能大部分时间都不在那里,或者你不确定,使用hasattr可能比反复陷入异常块更快。

我认为你正在寻找的是hasattr。然而,如果你想检测python属性-,我会推荐这样的东西。

try:getattr(someObject, 'someProperty')except AttributeError:print "Doesn't exist"elseprint "Exists"

这里的缺点是属性__get__代码中的属性错误也会被捕获。

否则,做

if hasattr(someObject, 'someProp'):#Access someProp/ set someProppass

文档:http://docs.python.org/library/functions.html
警告:
我推荐的原因是hasattr不检测属性。
链接:http://mail.python.org/pipermail/python-dev/2005-December/058498.html

根据pydoc,hasattr(obj, prop)简单地调用getattr(obj, prop)并捕获异常。因此,使用try语句包装属性访问并捕获属性错误与事先使用hasattr()一样有效。

a = SomeClass()try:return a.fake_propexcept AttributeError:return default_value

正如贾雷特·哈迪回答的那样,hasattr会起作用。不过,我想补充一点,Python社区中的许多人推荐“请求原谅比请求许可更容易”(EAFP)而不是“三思而后行”(LBYL)的策略。参见这些参考资料:

EAFP vs LBYL(回复:到目前为止有点失望)
EAFP vs. LBYL@像Pythonista一样的代码:惯用的Python

即:

try:doStuff(a.property)except AttributeError:otherStuff()

…优先于:

if hasattr(a, 'property'):doStuff(a.property)else:otherStuff()

根据情况,你可以用isinstance检查你有什么样的对象,然后使用相应的属性。随着Python 2.6/3.0中抽象基类的引入,这种方法也变得更加强大(基本上ABC允许更复杂的鸭子类型)。

这很有用的一种情况是,如果两个不同的对象具有相同名称但具有不同含义的属性。仅使用hasattr可能会导致奇怪的错误。

一个很好的例子是迭代器和迭代器之间的区别(参见这个问题)。迭代器和迭代器中的__iter__方法具有相同的名称,但语义上完全不同!所以hasattr是无用的,但isinstance和ABC一起提供了一个干净的解决方案。

然而,我同意在大多数情况下hasattr方法(在其他答案中描述)是最合适的解决方案。

您可以使用hasattr()或catch1,但如果您真的只是想要属性的值,如果它不存在,那么最好的选择就是使用#2

getattr(a, 'property', 'default value')

我建议避免这种情况:

try:doStuff(a.property)except AttributeError:otherStuff()

用户@jpalecek提到:如果doStuff()中出现AttributeError,则您丢失了。

也许这种方法更好:

try:val = a.propertyexcept AttributeError:otherStuff()else:doStuff(val)

希望你期待hasattr(),但尽量避免hasattr(),请选择getattr()。getattr()比hasattr()快

使用hasattr():

 if hasattr(a, 'property'):print a.property

同样在这里,我使用getattr来获取属性,如果没有属性,它返回无

   property = getattr(a,"property",None)if property:print property

编辑:这种方法有严重的局限性。如果对象是迭代,它应该可以工作。请查看下面的评论。

如果您像我一样使用python3.6或更高版本,则有一个方便的替代方案来检查对象是否具有特定属性:

if 'attr1' in obj1:print("attr1 = {}".format(obj1["attr1"]))

但是,我不确定现在哪个是最好的方法。使用hasattr(),使用getattr()或使用in。欢迎评论。

您可以使用hasattr内置方法检查object是否包含属性。

例如,如果您的对象是a并且您想检查属性stuff

>>> class a:...     stuff = "something"...>>> hasattr(a,'stuff')True>>> hasattr(a,'other_stuff')False

方法签名本身是hasattr(object, name) -> bool,这意味着如果object属性,它被传递给hasattr中的第二个参数,而不是根据对象中name属性的存在给出布尔值TrueFalse

这是超级简单的,只需使用dir(对象)
这将返回对象的每个可用函数和属性的列表。

这是一个非常直观的方法:

if 'property' in dir(a):a.property

另一个可能的选择,但这取决于你所说的之前是什么意思:

undefined = object()
class Widget:
def __init__(self):self.bar = 1
def zoom(self):print("zoom!")
a = Widget()
bar = getattr(a, "bar", undefined)if bar is not undefined:print("bar:%s" % (bar))
foo = getattr(a, "foo", undefined)if foo is not undefined:print("foo:%s" % (foo))
zoom = getattr(a, "zoom", undefined)if zoom is not undefined:zoom()

输出:

bar:1zoom!

这甚至允许您检查无值属性。

但是!要非常小心,不要意外地实例化和比较undefined多个位置,因为is在这种情况下永远不会起作用。

更新时间:

因为我在上面的段落中警告过,有多个从未匹配的未定义,我最近稍微修改了这个模式:

undefined = NotImplemented

不要与NotImplementedError混淆,NotImplemented是一个内置的:它半匹配JSundefined的意图,您可以在任何地方重用它的定义,并且它将始终匹配。缺点是它在布尔值中是“true”的,并且在日志和堆栈跟踪中看起来很奇怪(但是当您知道它只出现在这个上下文中时,您很快就会克服它)。

hasattr()是正确答案。我想补充的是,hasattr()可以很好地与断言结合使用(避免不必要的if语句,使代码更具可读性):

assert hasattr(a, 'property'), 'object lacks property'print(a.property)

如果缺少该属性,程序将以AssertionError退出并打印出提供的错误消息(在本例中为object lacks property)。

正如另一个关于so的回答所述:

断言应该用于测试不应该发生的条件。目的是在程序状态损坏的情况下提前崩溃。

通常情况下,当一个属性丢失,然后assert是非常合适的。

对于字典以外的对象:

if hasattr(a, 'property'):a.property

对于字典,hasattr()将不起作用。

许多人告诉使用has_key()作为字典,但它被贬值了。所以对于字典,你必须使用has_attr()

if a.has_attr('property'):a['property'] 

或者您也可以使用

if 'property' in a:

您可以使用有at tr()来检查对象或类是否在Python中具有属性。

例如,有#0类如下所示:

class Person:greeting = "Hello"
def __init__(self, name, age):self.name = nameself.age = age
def test(self):print("Test")

然后,您可以将有at tr()用于对象,如下所示:

obj = Person("John", 27)obj.gender = "Male"print("greeting:", hasattr(obj, 'greeting'))print("name:", hasattr(obj, 'name'))print("age:", hasattr(obj, 'age'))print("gender:", hasattr(obj, 'gender'))print("test:", hasattr(obj, 'test'))print("__init__:", hasattr(obj, '__init__'))print("__str__:", hasattr(obj, '__str__'))print("__module__:", hasattr(obj, '__module__'))

输出:

greeting: Truename: Trueage: Truegender: Truetest: True__init__: True__str__: True__module__: True

并且,您也可以将有at tr()直接用于类名,如下所示:

print("greeting:", hasattr(Person, 'greeting'))print("name:", hasattr(Person, 'name'))print("age:", hasattr(Person, 'age'))print("gender:", hasattr(Person, 'gender'))print("test:", hasattr(Person, 'test'))print("__init__:", hasattr(Person, '__init__'))print("__str__:", hasattr(Person, '__str__'))print("__module__:", hasattr(Person, '__module__'))

输出:

greeting: Truename: Falseage: Falsegender: Falsetest: True__init__: True__str__: True__module__: True