如何知道对象在Python中是否具有属性

Luc*_*hez 1491 python attributes

有没有办法在Python中确定对象是否具有某些属性?例如:

>>> a = SomeClass()
>>> a.someProperty = value
>>> a.property
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'
Run Code Online (Sandbox Code Playgroud)

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

Jar*_*die 2114

试试hasattr():

if hasattr(a, 'property'):
    a.property
Run Code Online (Sandbox Code Playgroud)

编辑:请参阅下面的zweiterlinde的答案,谁提供了关于请求宽恕的好建议!一种非常pythonic的方法!

python中的一般做法是,如果属性可能在大多数时间都存在,只需调用它并让异常传播,或者使用try/except块捕获它.这可能会比hasattr.如果该属性可能在大多数时间不存在,或者您不确定,使用hasattr可能会比重复进入异常块更快.

  • 似乎也在检查命名空间中的函数,例如:`import string hasattr(string,"lower")` (17认同)
  • `hasattr`与使用`try` /`完全相同,除了AttributeError`:hasattr的docstring(在Python 2.7中)说它使用getattr hand catches exception. (13认同)
  • @JeffTratner:遗憾的是,`hasattr`与`try:...除了属性错误:`之外的*完全*相同,因为`hasattr`将**捕获所有异常**.有关示例和简单的解决方法,请参阅[我的回答](http://stackoverflow.com/a/16186050/110204). (6认同)
  • 可以为“self”的属性完成吗?就像对象创建的“__init__()”中的“if not hasattr(self, 'property')” (3认同)
  • 如果您有理解的话,“ hasattr”也是一个不错的选择,例如“ [a.property in list_of_as as hasattr(a,“ property”)]“ (2认同)
  • 如果您的对象是“dict”,则 hasattr 不起作用。在这些情况下使用 in 运算符或 haskey 方法。 (2认同)

zwe*_*nde 581

正如Jarret Hardie回答的那样,hasattr会做到这一点.不过,我想补充一点,Python社区中的许多人都建议采用"更容易请求宽恕而不是许可"(EAFP)的策略,而不是"在你跳跃之前先看"(LBYL).见这些参考文献:

EAFP vs LBYL(Re:有点失望)
EAFP vs. LBYL @Code就像Pythonista:惯用语Python

即:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()
Run Code Online (Sandbox Code Playgroud)

...优先:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()
Run Code Online (Sandbox Code Playgroud)

  • EAFP似乎......疯了.HasAttr致电未来的维护程序员,您正在检查特定属性.获得一个例外可以告诉未来的程序员什 (257认同)
  • 但是你如何检查它是导致AttributeError的a.property,而不是doStuff()中的东西?看来你没有.我认为要求宽恕真的很容易,但很多时候,这也是不正确的. (244认同)
  • @ e5:在这种情况下你有一个公平的观点,但在很多情况下,EAFP是唯一正确的选择.例如,如果检查文件的存在然后打开它,期望它肯定存在,则代码不正确:文件可能会在检查和使用之间被删除或重命名.这称为TOCTOU错误(使用时间检查时间),除了导致崩溃之外,还可能是安全漏洞的来源. (72认同)
  • 这里的大多数含糊不清的投诉仅仅是因为示例代码结构不合理.`try:`中唯一的内容应该是尝试的属性访问; 也没有理由包装`doStuff`的执行.但是仍然存在一些模糊性:如果`property`是计算属性而不是普通属性,它的实现可能会在内部引发`AttributeError`.这就是为什么在几乎所有这样的实际情况中,`getattr`比`hasattr`或捕捉`AttributeError`更可取. (59认同)
  • @EthanHeilman当异常来源存在歧义时,它才会疯狂,在大多数情况下可以通过良好的设计来避免.在try/except/finally中良好分层的逻辑结构通常比使用对每条消费代码的抢先if-check乱丢代码更有效(更少程序员容易出错)的逻辑.使错误也非常明确,并允许程序员直接处理它们. (14认同)
  • 如果您只需要在某个属性存在时执行某些操作,否则什么也不执行,该怎么办?你会做“尝试”-“除了:通过”吗?它效率低下,而且风格也不好,因为它不是您在这里处理的实际异常或错误,它是没有特定属性的对象的程序的预期流程。 (4认同)
  • @scot异常不适用于python中的特殊情况,也不会给性能增加任何重大开销.这就是EAFP首选的原因.如果与if else结构相比,这掩盖了逻辑,则取决于上下文. (2认同)
  • @scot:早点停止三个字:例外是针对特殊情况.这些特殊情况是否会导致某些概念上的错误并不重要; 关键是你可以不间断地编写"正常"控制流程,并处理具有异常的"例外"情况. (2认同)

Car*_*yer 444

你可以使用hasattr()或者捕获AttributeError,但是如果你真的只想要属性的值,如果它不存在,那么最好的选择就是使用getattr():

getattr(a, 'property', 'default value')
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的解决方案"如果你真的只想要属性的默认值." 虽然我相信这是许多人在说他们想要检测属性是否存在时实际想要的,但OP实际上要求后者,所以将该问题的直接答案(hasattr,AttributeError)列为更高是合理的. (15认同)
  • 这解决了上述两个问题:a)可能的AttributeError源的模糊性,b)保留EAFP方法. (12认同)
  • 它也是25%的代码行.当然,这必须是最好的解决方案. (6认同)

bat*_*rat 40

我认为你要找的是hasattr.但是,如果你想检测python属性,我会推荐这样的东西-

try:
    getattr(someObject, 'someProperty')         
except AttributeError:
    print "Doesn't exist"
else
    print "Exists"
Run Code Online (Sandbox Code Playgroud)

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

否则,做 -

if hasattr(someObject, 'someProp'):
    #Access someProp/ set someProp
    pass
Run Code Online (Sandbox Code Playgroud)

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

  • “ hasattr”通常可以很好地检测属性。只是将“属性”包装的函数中的引发异常视为不存在此类属性;链接的Python邮件列表帖子是关于一个属性的,当您尝试访问它时会引发异常。出于所有实际目的,所述属性不存在,因为它永远不会产生值。同样,`hasattr`只抑制Py 3.1和更早版本的异常。在3.2及更高版本中,它仅抑制(以“ False”返回代替)“ AttributeError”。 (2认同)

Jor*_*wis 30

根据pydoc,hasattr(obj,prop)只需调用getattr(obj,prop)并捕获异常.因此,使用try语句包装属性访问并捕获AttributeError同样有效,因为它是事先使用hasattr().

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value
Run Code Online (Sandbox Code Playgroud)

  • +1.这甚至比使用`hasattr`更安全*当`SomeClass`覆盖`__getattr__`,因为`hasattr`将捕获**2.x中的所有**异常,而不仅仅是你想要的`AttributeError`.这已在Python 3.2中修复 - 请参阅[我的其他答案](http://stackoverflow.com/a/16186050/110204)以获得简单的解决方法. (6认同)
  • 好吧,实际上*可以*优化.例如与pypy. (2认同)

Mai*_*ico 23

我想建议避免这个:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()
Run Code Online (Sandbox Code Playgroud)

用户@jpalecek提到它:如果AttributeError内部发生doStuff(),你就会迷路.

也许这种方法更好:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)
Run Code Online (Sandbox Code Playgroud)


F.M*_*.F. 23

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

assert hasattr(a, 'property'), 'object lacks property' 
print(a.property)
Run Code Online (Sandbox Code Playgroud)

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

正如SO 的另一个答案中所述:

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

通常情况下,当某个属性缺失但又assert非常合适时,就会出现这种情况。

  • 这很有帮助,但情况可能并不总是如此。也许我想测试该对象是否具有属性,然后第一次添加它,或者我可能必须为具有该属性的对象运行不同的代码。当代码无法继续时,断言可能没问题。但话又说回来,情况并非总是如此。重要的是使用“hasattr”而不是周围的代码。 (2认同)

Sha*_*shi 23

对于字典以外的对象:

if hasattr(a, 'property'):
    a.property
Run Code Online (Sandbox Code Playgroud)

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

很多人都说用has_key()字典,但它已经贬值了。所以对于字典,你必须使用has_attr()

if a.has_attr('property'):
    a['property']
 
Run Code Online (Sandbox Code Playgroud)

或者你也可以使用

if 'property' in a:
Run Code Online (Sandbox Code Playgroud)

  • 对于 dict,请使用 `if 'property' in a:` (3认同)

nik*_*kow 12

根据具体情况,您可以检查isinstance您拥有的对象类型,然后使用相应的属性.随着Python 2.6/3.0 中抽象基类的引入,这种方法也变得更加强大(基本上ABCs允许更复杂的鸭子打字方式).

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

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

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


Jan*_*amu 11

希望你期待hasattr(),但尽量避免使用hasattr(),请更喜欢getattr().getattr()比hasattr()更快

使用hasattr():

 if hasattr(a, 'property'):
     print a.property
Run Code Online (Sandbox Code Playgroud)

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

   property = getattr(a,"property",None)
    if property:
        print property
Run Code Online (Sandbox Code Playgroud)

  • 但如果该属性确实存在并且其值为“False”,您最终可能会得到误报。 (3认同)
  • @Groosha有很​​多事情,为了使其简单,hasattr() 内部必须调用 getattr() 来执行其操作,因此我们可以使用直接 getattr() 检查此 https://docs.python.org/,而不是调用多个方法3/library/functions.html#hasattr (2认同)

nay*_*yak 10

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

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

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))
Run Code Online (Sandbox Code Playgroud)

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

  • `in`关键字用于检查可迭代类型.例如,None`中的''foo'抛出错误`TypeError:类型'NoneType'的参数不可迭代`.修复是在使用`in`之前检查类型是否可迭代.在校正像非迭代类型这样的边缘情况之后,你可能最好使用`hasattr()`,因为它的设计是为了处理边缘情况. (5认同)
  • 这与属性访问无关.我不知道它是如何被投票的.它与属性访问的唯一相似之处在于,如果您使用`dict`作为"轻量级对象",类似于JavaScript对象的设计,但大多数普通类通常不支持这种情况(获取上述错误的变体) @SethDifley). (2认同)
  • 如果类中的变量是__dict__:? (2认同)

Ale*_*ine 10

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

if 'property' in dir(a):
    a.property
Run Code Online (Sandbox Code Playgroud)


小智 6

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

例如有如下所示的Person类:

class Person:
    greeting = "Hello"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def test(self):
        print("Test")
Run Code Online (Sandbox Code Playgroud)

然后,您可以对对象使用hasattr(),如下所示:

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__'))
Run Code Online (Sandbox Code Playgroud)

输出:

greeting: True
name: True
age: True
gender: True
test: True
__init__: True
__str__: True
__module__: True
Run Code Online (Sandbox Code Playgroud)

并且,您还可以直接使用hasattr()作为类名,如下所示:

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__'))
Run Code Online (Sandbox Code Playgroud)

输出:

greeting: True
name: False
age: False
gender: False
test: True
__init__: True
__str__: True
__module__: True
Run Code Online (Sandbox Code Playgroud)