Python hasattr与getattr [英] Python hasattr vs getattr
问题描述
我最近一直在阅读一些 tweets 和关于hasattr的python文档,其中说:
I have been reading lately some tweets and the python documentation about hasattr and it says:
hasattr(object,名称)
hasattr(object, name)
参数是一个对象和一个字符串。如果字符串是对象属性之一的名称>>,则结果为True,否则为False。 (这是通过调用
getattr(object,name)并查看它是否引发AttributeError来实现的。)
Python中有一个座右铭,那就是我通常会同意比许可更容易获得宽恕。
There is a motto in Python that says that is Easier to ask for forgiveness than permission where I usually agree.
在这种情况下,我尝试使用一个非常简单的python代码进行性能测试:
I tried to do a performance test in this case with a really simple python code:
import timeit
definition="""\
class A(object):
a = 1
a = A()
"""
stm="""\
hasattr(a, 'a')
"""
print timeit.timeit(stmt=stm, setup=definition, number=10000000)
stm="""\
getattr(a, 'a')
"""
print timeit.timeit(stmt=stm, setup=definition, number=10000000)
结果为:
$ python test.py
hasattr(a, 'a')
1.26515984535
getattr(a, 'a')
1.32518696785
我还尝试了如果该属性不存在并且getattr和hasattr之间的差异较大时会发生什么情况。因此,到目前为止,我所看到的是getattr比hasattr慢,但是在文档中说它叫做getattr。
I´ve tried also what happens if the attribute doesn´t exists and the differences between getattr and hasattr are bigger. So what I´ve seen so far is that getattr is slower than hasattr, but in the documentation it says that it calls getattr.
我已经搜索了CPython实现 hasattr 和getattr ,而且似乎都调用了下一个函数:
I´ve searched the CPython implementation of hasattr and getattr and it seems that both call the next function:
v = PyObject_GetAttr(v, name);
但是getattr中的样板文件比hasattr中的样板文件要慢得多。
but there is more boilerplate in getattr than in hasattr that probably makes it slower.
有人知道在文档中为什么我们说hasattr调用getattr吗?我们似乎鼓励用户在实际上不是由于性能而使用getattr代替hasattr吗?
Does anyone knows why in the documentation we say that hasattr calls getattr and we seem to encourage the users to use getattr instead of hasattr when it really isn´t due to performance? Is just because it is more pythonic?
也许我在测试中做错了:)
Maybe I am doing something wrong in my test :)
谢谢,
劳尔
推荐答案
文档不鼓励使用,该文档只是说显而易见的。 hasattr
是这样实现的,从属性获取器中抛出 AttributeError
可以使该属性看起来像存在。这是一个重要的细节,这就是在文档中明确说明的原因。例如考虑以下代码:
The documentation does not encourage, the documentation just states the obvious. The hasattr
is implemented as such, and throwing an AttributeError
from a property getter can make it look like the attribute does not exist. This is an important detail, and that is why it is explicitly stated in the documentation. Consider for example this code:
class Spam(object):
sausages = False
@property
def eggs(self):
if self.sausages:
return 42
raise AttributeError("No eggs without sausages")
@property
def invalid(self):
return self.foobar
spam = Spam()
print(hasattr(Spam, 'eggs'))
print(hasattr(spam, 'eggs'))
spam.sausages = True
print(hasattr(spam, 'eggs'))
print(hasattr(spam, 'invalid'))
结果是
True
False
True
False
这是垃圾邮件
类具有用于鸡蛋
,但由于如果不是self.sausages
,则getter会引发 AttributeError
,因此该实例类不 有麻烦
鸡蛋
。
That is the Spam
class has a property descriptor for eggs
, but since the getter raises AttributeError
if not self.sausages
, then the instance of that class does not "hasattr
" eggs
.
Oth除此之外,仅在不需要该值时使用 hasattr
;如果需要该值,请使用带有两个参数的 getattr
并捕获异常或3个参数,第三个是明智的默认值。
Other than that, use hasattr
only when you don't need the value; if you need the value, use getattr
with 2 arguments and catch the exception, or 3 arguments, the third being a sensible default value.
使用 getattr()
(2.7.9)的结果:
The results using getattr()
(2.7.9):
>>> spam = Spam()
>>> print(getattr(Spam, 'eggs'))
<property object at 0x01E2A570>
>>> print(getattr(spam, 'eggs'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in eggs
AttributeError: No eggs without sausages
>>> spam.sausages = True
>>> print(getattr(spam, 'eggs'))
42
>>> print(getattr(spam, 'invalid'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in invalid
AttributeError: 'Spam' object has no attribute 'invalid'
>>>
这篇关于Python hasattr与getattr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!