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

How to check if an object has an attribute?

提问人:Lucas Gabriel Sánchez 提问时间:3/4/2009 最后编辑:Super Kai - Kazuya ItoLucas Gabriel Sánchez 更新时间:8/5/2023 访问量:1416106

问:

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

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

在使用之前,如何判断它是否具有该属性?aproperty

Python 对象 属性 错误

评论

0赞 smci 2/28/2022
当你说“在使用它之前判断 a 是否具有属性属性?”时,你是想要一个返回布尔值的函数(如返回值),还是可以抛出异常?hasattr()AttributeError
4赞 smci 2/28/2022
另外,实际上不要将您的属性命名为“property”,因为 Python 也有属性装饰器和内置属性,它们与普通属性/方法略有不同。

答:

3372赞 Jarret Hardie 3/4/2009 #1

试试 hasattr()

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

请看下面 zweiterlinde 的回答,他提供了关于请求宽恕的好建议!一个非常蟒蛇的方法!

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

评论

28赞 riviera 4/8/2011
似乎也适用于检查命名空间中的函数,例如:import string hasattr(string, "lower")
23赞 Jeff Tratner 4/27/2012
hasattr与使用 / 完全相同:hasattr 的文档字符串(在 Python 2.7 中)说它使用 getattr 手动捕获异常。tryexcept AttributeError
11赞 Martin Geisler 4/24/2013
@JeffTratner:不幸的是,它与Python 2.x中的a并不完全相同,因为会捕获所有异常。请参阅我的回答以获取示例和简单的解决方法。hasattrtry: ... except AttributeError:hasattr
2赞 AnandShiva 4/4/2021
如果您的对象是“dict”,则 hasattr 不起作用。在这些情况下,使用 in 运算符或 haskey 方法。
3赞 alper 9/14/2021
属性可以做吗?就像在对象创建内部一样selfif not hasattr(self, 'property')__init__()
55赞 batbrat 3/4/2009 #2

我想你要找的是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

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

评论

4赞 ShadowRanger 4/26/2018
hasattr检测属性一般就好了。只是它将在 -wrapped 函数中引发异常视为表示不存在此类属性;链接的 Python 邮件列表帖子是关于一个属性,当您尝试访问它时会引发异常。出于所有实际目的,所述属性不存在,因为它永远不会产生值。此外,仅在 Py 3.1 及更早版本上通常禁止异常;在 3.2+ 中,它只抑制(替换为 return)。propertyhasattrFalseAttributeError
40赞 Jordan Lewis 3/4/2009 #3

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

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

评论

3赞 odinho - Velmont 8/19/2011
好吧,hasattr实际上可以优化。例如,使用 pypy。
7赞 Martin Geisler 4/24/2013
+1.这甚至比在重写时使用更安全,因为会捕获 Python 2.x 中的所有异常,而不仅仅是您期望的那样。这在 Python 3.2 中已修复 - 请参阅我的其他答案以获取简单的解决方法。hasattrSomeClass__getattr__hasattrAttributeError
821赞 zweiterlinde 3/4/2009 #4

正如贾雷特·哈迪(Jarret Hardie)所回答的那样,将做到这一点。不过,我想补充一点,Python 社区中的许多人推荐了一种“请求宽恕比请求许可更容易”(EAFP) 的策略,而不是“先看后跳”(LBYL)。请参阅以下参考资料:hasattr

EAFP vs LBYL(回复:到目前为止有点失望)
EAFP vs. LBYL @Code Like a Pythonista:惯用的 Python

结婚

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

...优于:

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

评论

354赞 jpalecek 4/14/2009
但是你如何检查是 a.property 导致了 AttributeError,而不是 doStuff() 中的东西?看来你没有。我认为请求原谅确实更容易,但很多时候,这也是不正确的。
383赞 Ethan Heilman 10/15/2010
EAFP似乎......疯。HasAttr 向未来的维护程序员发送电报,表明您正在检查特定属性。获得异常不会告诉未来的程序员任何事情,并且可能会将某人带入兔子洞。
89赞 Max 6/1/2011
@e5:在这种情况下,你有一个公平的观点,但在许多情况下,EAFP是唯一正确的选择。例如,如果您检查一个文件是否存在,然后打开它,期望它肯定会存在,那么您的代码不正确:该文件可能会在检查和使用之间被删除或重命名。这称为 TOCTOU 错误(Check-To-Time-Of-Use),除了导致崩溃之外,还可能是安全漏洞的来源。
23赞 Peter M. Elias 1/3/2013
@EthanHeilman只有当异常的来源存在歧义时,它才是疯狂的,在大多数情况下,这可以通过良好的设计来避免。try/except / finally中逻辑的分层结构通常比在代码中为每段消耗代码提供先发制人的if检查来破坏逻辑更健壮(不容易出错)。使错误也非常明确,并允许使用程序员选择直接处理它们。
80赞 Carl Meyer 9/25/2013
这里的大多数歧义抱怨仅仅是因为示例代码结构不佳。里面唯一应该尝试的属性访问;也没有理由包装执行。但是,仍然存在一些潜在的歧义:如果是计算属性而不是普通属性,则其实现可能会在内部引发。这就是为什么在几乎所有这样的真实情况下,都比 要么 要么 捕捉 .try:doStuffpropertyAttributeErrorgetattrhasattrAttributeError
17赞 nikow 3/4/2009 #5

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

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

一个很好的例子是迭代器和可迭代对象之间的区别(请参阅问题)。迭代器和可迭代对象中的方法具有相同的名称,但在语义上却大不相同!所以是无用的,但与ABC一起提供了一个干净的解决方案。__iter__hasattrisinstance

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

657赞 Carl Meyer 3/5/2009 #6

你可以使用 或 catch ,但如果你真的只想使用默认值的属性值(如果它不存在),最好的选择是使用 getattr():hasattr()AttributeError

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

评论

19赞 Peter M. Elias 1/3/2013
这解决了上述两个问题:a) 可能的 AttributeError 源的模糊性,b) 保留 EAFP 方法。
10赞 fatuhoku 9/24/2013
它也是代码行数的 25%。当然,这一定是最好的解决方案。
23赞 Carl Meyer 12/1/2015
这是最好的解决方案,“如果你真的只想要一个默认值的属性值。虽然我相信这是许多人在说他们想要检测某个属性是否存在时真正想要的,但 OP 实际上要求后者,因此将该问题的直接答案(hasattr、AttributeError)列得更高是合理的。
0赞 Vexen Crabtree 6/24/2021
对提及“默认属性”投了赞成票。有时我需要这个,但忘记了!
0赞 Gryu 12/9/2022
在大多数情况下,这比我接受的答案要好得多,因为 hasattr 通常用于检查 attr 是否存在,然后检查其值以避免异常,这有助于直接检查值,而无需“if hasattr 并检查值”
36赞 Maico 8/26/2016 #7

我想建议避免这种情况:

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

用户@jpalecek提到:如果里面发生,你就迷路了。AttributeErrordoStuff()

也许这种方法更好:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)
18赞 Janarthanan Ramu 12/30/2016 #8

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

使用 hasattr():

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

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

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

评论

0赞 Groosha 7/25/2020
getattr() is faster than hasattr(),中方对此有何评论?为什么更快?
3赞 Janarthanan Ramu 7/28/2020
@Groosha 有很多事情,为了简单起见,hasattr() 内部必须调用 getattr() 来执行它们的操作,因此我们可以直接使用 getattr() 来代替调用多个方法检查此 docs.python.org/3/library/functions.html#hasattr
3赞 user9538 7/14/2021
但是,如果该属性确实存在并且其值为 ,则最终可能会出现误报。False
20赞 nayak 6/22/2017 #9

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

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

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

但是,我不确定目前哪种方法是最好的方法。使用 、 使用 或 使用 。欢迎评论。hasattr()getattr()in

评论

8赞 Seth Difley 10/5/2017
in关键字用于检查可迭代类型。例如,抛出错误 。解决方法是在使用 之前检查类型是否可迭代。在纠正了边缘情况(如不可迭代类型)之后,您可能最好使用,因为它旨在处理边缘情况。'foo' in NoneTypeError: argument of type 'NoneType' is not iterableinhasattr()
5赞 ShadowRanger 4/26/2018
这与属性访问无关。我不知道它是如何被点赞的。它与属性访问的唯一相似之处是,如果您用作“轻量级对象”,类似于 JavaScript 对象的设计,但大多数普通类通常不支持此功能(获取 @SethDifley 提到的错误的变体)。dict
3赞 Devang Padhiyar 3/9/2019 #10

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

对于实例,如果您的对象是,并且您想要检查属性astuff

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

方法签名本身意味着如果具有传递给第二个参数的属性,则它给出布尔值或根据对象中属性的存在。hasattr(object, name) -> boolobjecthasattrTrueFalsename

评论

0赞 Gabriel Staples 12/20/2021
nit:是一个函数,而不是一个方法。请看这里。hasattr()
4赞 Sean Christians 3/13/2019 #11

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

18赞 Alec 5/25/2019 #12

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

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

如果a是字典,可以正常检查

if 'property' in a:
    a.property

评论

0赞 MattSt 8/12/2022
很高兴知道这是可能的,但我建议不要使用 dir(),而是使用 hasattr()。函数 dir() 将找不到元类提供的属性。有关更多信息,请查看 stackoverflow.com/questions/17723569/...
0赞 JL Peyret 8/14/2019 #13

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

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:1
zoom!

这允许您检查无值属性。

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

更新:

由于我在上面的段落中警告过,有多个永远不匹配的未定义,我最近稍微修改了这个模式:

undefined = NotImplemented

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

23赞 F.M.F. 5/28/2020 #14

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

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

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

正如在关于 SO 的另一个回答中所述:

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

通常,当属性丢失时,情况就非常合适。assert

评论

2赞 Lucas Gabriel Sánchez 5/28/2020
这很有帮助,但可能并非总是如此。也许我想测试对象是否具有属性,然后首次添加它,或者我必须为具有该属性的对象运行不同的代码。当代码无法继续时,断言可能没问题。但同样,情况并非总是如此。重要的是使用不周围的代码。hasattr
23赞 Shashi 6/24/2021 #15

对于字典以外的对象:

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

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

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

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

或者你也可以使用

if 'property' in a:

评论

3赞 Martin Bonner supports Monica 5/4/2022
对于 dict,请使用if 'property' in a:
6赞 Super Kai - Kazuya Ito 11/16/2022 #16

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

例如,有如下所示的 Person

class Person:
    greeting = "Hello"

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

    def test(self):
        print("Test")

然后,你可以对对象使用 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__'))

输出:

greeting: True
name: True
age: True
gender: True
test: True
__init__: True
__str__: True
__module__: True

而且,您也可以直接使用 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__'))

输出:

greeting: True
name: False
age: False
gender: False
test: True
__init__: True
__str__: True
__module__: True