如何确定对象是否具有某些属性?例如:
>>> a = SomeClass()
>>> a.property
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'
在使用之前如何判断 a
是否具有属性 property
?
hasattr()
返回)还是可以抛出AttributeError
异常?
property
decorator and builtin,而且它们与普通属性/方法略有不同。
试试 hasattr()
:
if hasattr(a, 'property'):
a.property
请参阅下面的 zweiterlinde's answer,谁提供了关于请求宽恕的好建议!一个非常pythonic的方法!
python 中的一般做法是,如果该属性可能大部分时间都存在,只需调用它并让异常传播,或者使用 try/except 块捕获它。这可能会比 hasattr
快。如果该属性可能大部分时间都不存在,或者您不确定,则使用 hasattr
可能比反复陷入异常块更快。
正如 Jarret Hardie 回答的那样,hasattr
可以解决问题。不过,我想补充一点,Python 社区中的许多人建议采用“更容易请求宽恕而不是许可”(EAFP)而不是“在跳跃之前先看”(LBYL)的策略。请参阅这些参考资料:
EAFP vs LBYL (was Re: A little disappointed so far)
EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python
IE:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
...首选:
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
try:
内的唯一内容应该是尝试的属性访问;也没有理由包装 doStuff
的执行。但仍有一些歧义的可能性:如果 property
是计算属性而不是普通属性,则其实现可能会在内部引发 AttributeError
。这就是为什么在几乎所有像这样的实际情况下,getattr
都比 hasattr
或捕获 AttributeError
更可取。
您可以使用 hasattr()
或 catch AttributeError
,但如果您真的只希望该属性的值没有默认值,那么最好的选择就是使用 getattr()
:
getattr(a, 'property', 'default value')
我认为您正在寻找的是 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
通常可以很好地检测属性。只是它将在 property
包装的函数中引发异常视为不存在此类属性;链接的 Python 邮件列表帖子是关于在您尝试访问它时引发异常的属性。出于所有实际目的,所述属性不存在,因为它永远不会产生值。此外,hasattr
仅在 Py 3.1 及更早版本中抑制一般异常;在 3.2+ 中,它只抑制(替换为 False
返回)AttributeError
。
根据 pydoc, hasattr(obj, prop) 只需调用 getattr(obj, prop) 并捕获异常。因此,使用 try 语句包装属性访问并捕获 AttributeError 与预先使用 hasattr() 一样有效。
a = SomeClass()
try:
return a.fake_prop
except AttributeError:
return default_value
SomeClass
覆盖 __getattr__
时,这甚至比使用 hasattr
更安全,因为 hasattr
将捕获 Python 2.x 中的所有异常,而不仅仅是 AttributeError
就像你期望的那样。这已在 Python 3.2 中修复 — 请参阅 my other answer 了解简单的解决方法。
我想建议避免这种情况:
try:
doStuff(a.property)
except AttributeError:
otherStuff()
用户 @jpalecek 提到它:如果 AttributeError
出现在 doStuff()
中,你就迷路了。
也许这种方法更好:
try:
val = a.property
except AttributeError:
otherStuff()
else:
doStuff(val)
编辑:这种方法有严重的局限性。如果对象是可迭代的,它应该可以工作。请检查下面的评论。
如果您像我一样使用 Python 3.6 或更高版本,则有一个方便的替代方法来检查对象是否具有特定属性:
if 'attr1' in obj1:
print("attr1 = {}".format(obj1["attr1"]))
但是,我不确定哪个是目前最好的方法。使用 hasattr()
、使用 getattr()
或使用 in
。欢迎评论。
in
关键字用于检查可迭代类型。例如,'foo' in None
会引发错误 TypeError: argument of type 'NoneType' is not iterable
。修复方法是在使用 in
之前检查类型是否可迭代。在纠正了不可迭代类型等边缘情况后,您最好使用 hasattr()
,因为它旨在处理边缘情况。
dict
作为“轻量级对象”,类似于 JavaScript 对象的设计,但大多数普通类通常不支持这一点(获取关于错误的变体@SethDifley)。
hasattr()
是正确答案。我要补充的是,hasattr()
也可以很好地与 assert 结合使用(以避免不必要的 if
语句并使代码更具可读性):
assert hasattr(a, 'property'), 'object lacks property'
print(a.property)
如果缺少该属性,程序将退出并显示 AssertionError
并打印出提供的错误消息(在本例中为 object lacks property
)。
如另一个 answer on SO 所述:
断言应该用于测试不应该发生的情况。目的是在程序状态损坏的情况下尽早崩溃。
这通常是缺少某个属性然后 assert
非常合适的情况。
hasattr
而不是周围的代码。
根据情况你可以用isinstance
检查你有什么样的对象,然后使用相应的属性。随着在 Python 2.6/3.0 中引入 abstract base classes,这种方法也变得更加强大(基本上 ABC 允许更复杂的鸭子类型)。
一种有用的情况是,如果两个不同的对象具有同名但含义不同的属性。仅使用 hasattr
可能会导致奇怪的错误。
一个很好的例子是迭代器和可迭代对象之间的区别(参见 this 问题)。迭代器和可迭代对象中的 __iter__
方法名称相同,但语义完全不同!所以 hasattr
是无用的,但 isinstance
与 ABC 一起提供了一个干净的解决方案。
但是,我同意在大多数情况下,hasattr
方法(在其他答案中描述)是最合适的解决方案。
希望你期待 hasattr(),但尽量避免 hasattr(),请更喜欢 getattr()。 getattr() 比 hasattr() 快
使用 hasattr():
if hasattr(a, 'property'):
print a.property
同样在这里我使用 getattr 来获取属性,如果没有属性它返回 none
property = getattr(a,"property",None)
if property:
print property
getattr() is faster than hasattr()
,您能对此发表评论吗?为什么更快?
False
,则您最终可能会误报。
对于字典以外的对象:
if hasattr(a, 'property'):
a.property
对于字典,hasattr()
不起作用。
许多人告诉使用 has_key()
作为字典,但它已被贬值。所以对于字典,你必须使用 has_attr()
if a.has_attr('property'):
a['property']
if 'property' in a:
这是一个非常直观的方法:
if 'property' in dir(a):
a.property
这非常简单,只需使用 dir(
object)
这将返回对象的每个可用函数和属性的列表。
您可以使用 hasattr
内置方法检查 object
是否包含属性。
例如,如果您的对象是 a
,并且您想要检查属性 stuff
>>> class a:
... stuff = "something"
...
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False
方法签名本身是 hasattr(object, name) -> bool
,这意味着如果 object
具有传递给 hasattr
中的第二个参数的 attribute,则它会根据 True
的存在给出布尔值 True
或 False
6} 对象中的属性。
hasattr()
是一个函数,而不是一个方法。 See here.
另一种可能的选择,但这取决于您之前的意思:
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!
这使您甚至可以检查无值属性。
但!请非常小心,不要意外实例化并比较多个位置 undefined
,因为 is
在这种情况下将永远无法工作。
更新:
由于我在上一段中警告过,有多个从不匹配的未定义,我最近稍微修改了这个模式:
undefined = NotImplemented
NotImplemented
,不要与 NotImplementedError
混淆,是一个内置的:它半匹配 JS undefined
的意图,您可以在任何地方重用它的定义,它总是匹配的。缺点是它在布尔值中是“真实的”,并且在日志和堆栈跟踪中看起来很奇怪(但是当你知道它只出现在这个上下文中时你很快就会克服它)。
不定期副业成功案例分享
import string hasattr(string, "lower")
hasattr
与使用try
/except AttributeError
完全相同:hasattr 的文档字符串(在 Python 2.7 中)表示它使用 getattr 手动捕获异常。hasattr
与 Python 2.x 中的try: ... except AttributeError:
并不完全相同,因为hasattr
将捕获所有异常。有关示例和简单的解决方法,请参阅 my answer。self
的属性完成吗?像对象创建的__init__()
内的if not hasattr(self, 'property')