当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何知道对象在Python中是否具有属性》经验,为你挑选了9个好方法。

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

>>> a = SomeClass()
>>> a.someProperty = value
>>> a.property
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: SomeClass instance has no attribute 'property'

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



1> Jarret Hardi..:

试试hasattr():

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

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

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


似乎也在检查命名空间中的函数,例如:`import string hasattr(string,"lower")`
`hasattr`与使用`try` /`完全相同,除了AttributeError`:hasattr的docstring(在Python 2.7中)说它使用getattr hand catches exception.
@JeffTratner:遗憾的是,`hasattr`与`try:...除了属性错误:`之外的*完全*相同,因为`hasattr`将**捕获所有异常**.有关示例和简单的解决方法,请参阅[我的回答](http://stackoverflow.com/a/16186050/110204).
如果您有理解的话,“ hasattr”也是一个不错的选择,例如“ [a.property in list_of_as as hasattr(a,“ property”)]“

2> zweiterlinde..:

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

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

即:

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

...优先:

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


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

3> Carl Meyer..:

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

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


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

4> batbrat..:

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

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

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

否则,做 -

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

文档: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”。

5> Jordan Lewis..:

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

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value


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

6> Maico..:

我想建议避免这个:

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

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

也许这种方法更好:

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



7> nikow..:

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

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

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

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



8> Janarthanan ..:

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

使用hasattr():

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

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

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



9> nayak..:

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

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

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

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


`in`关键字用于检查可迭代类型.例如,None`中的''foo'抛出错误`TypeError:类型'NoneType'的参数不可迭代`.修复是在使用`in`之前检查类型是否可迭代.在校正像非迭代类型这样的边缘情况之后,你可能最好使用`hasattr()`,因为它的设计是为了处理边缘情况.
这与属性访问无关.我不知道它是如何被投票的.它与属性访问的唯一相似之处在于,如果您使用`dict`作为"轻量级对象",类似于JavaScript对象的设计,但大多数普通类通常不支持这种情况(获取上述错误的变体) @SethDifley).
如果类中的变量是__dict__:?
推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有