首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python hasattr vs getattr

Python hasattr vs getattr
EN

Stack Overflow用户
提问于 2014-07-26 12:32:06
回答 2查看 26.4K关注 0票数 14

我最近读了一些关于哈扎特的推特python文档,上面写着:

哈萨特(对象,名称) 参数是一个对象和一个字符串。如果字符串是对象的属性之一>>的名称,则结果为True,如果不是,则为False。(这是通过调用getattr(对象、名称)并查看它是否引发AttributeError来实现的)

在Python中有一句格言说,比许可更容易请求原谅,在这里我通常是同意的。

在本例中,我尝试用一个非常简单的python代码进行性能测试:

代码语言:javascript
复制
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)

其结果如下:

代码语言:javascript
复制
$ python test.py
hasattr(a, 'a')
1.26515984535

getattr(a, 'a')
1.32518696785

我也尝试过,如果属性不存在,并且getattr和hasattr之间的差异更大,会发生什么。到目前为止,我看到的是getattr比hasattr慢,但是在文档中它说它叫getattr。

我已经搜索了哈萨特getattr哈萨特实现,并且似乎都调用了下一个函数:

代码语言:javascript
复制
v = PyObject_GetAttr(v, name);

但是getattr中的样板比hasattr中的样板更多,这可能会使它变慢。

有谁知道为什么在文档中我们说hasattr调用getattr,并且我们似乎鼓励用户使用getattr而不是hasattr,而不是因为性能原因呢?仅仅是因为它更多的是琵琶?

也许我在考试中做错了什么:)

谢谢,

劳尔

EN

回答 2

Stack Overflow用户

发布于 2014-07-26 12:43:01

文档并不鼓励,文档只是陈述了显而易见的事实。hasattr就是这样实现的,从属性getter中抛出一个AttributeError可以使它看起来像是不存在属性。这是一个重要的细节,这就是为什么在文档中明确说明这一点的原因。例如,考虑以下代码:

代码语言:javascript
复制
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'))

结果是

代码语言:javascript
复制
True
False
True
False

也就是说,Spam类有一个eggs的属性描述符,但是由于getter会引发AttributeError if not self.sausages,那么该类的实例并不是"hasattreggs

除此之外,只在hasattr不需要值时才使用;如果需要值,则使用带有2个参数的getattr并捕获异常或3个参数,第三个参数是合理的默认值。

使用getattr()的结果(2.7.9):

代码语言:javascript
复制
>>> 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'
>>>
票数 23
EN

Stack Overflow用户

发布于 2015-09-15 21:58:21

似乎hasattr在吞咽异常(至少是在Python 2.7中)方面有问题,所以最好在修复之前远离它。

以下代码为例

代码语言:javascript
复制
>>> class Foo(object):
...     @property
...     def my_attr(self):
...         raise ValueError('nope, nope, nope')
...
>>> bar = Foo()
>>> bar.my_attr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in my_attr
ValueError: nope, nope, nope
>>> hasattr(Foo, 'my_attr')
True
>>> hasattr(bar, 'my_attr')
False
>>> getattr(bar, 'my_attr', None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in my_attr
ValueError: nope, nope, nope
>>>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24971061

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档