【发布时间】:2014-09-18 05:06:59
【问题描述】:
我最近一直在阅读一些关于 hasattr 的 tweets 和 python documentation,上面写着:
hasattr(对象,名称)
参数是一个对象和一个字符串。如果字符串是 >> 对象属性之一的名称,则结果为 True,否则为 False。 (这是通过调用实现的 getattr(object, name) 并查看它是否引发 AttributeError。)
Python 中有一句格言是请求宽恕比请求许可更容易,我通常同意这一点。
在这种情况下,我尝试使用非常简单的 python 代码进行性能测试:
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。
我搜索了 hasattr 和 getattr 的 CPython 实现,似乎都调用了下一个函数:
v = PyObject_GetAttr(v, name);
但 getattr 中的样板文件比 hasattr 中的多,这可能会使其变慢。
有谁知道为什么在文档中我们说 hasattr 调用 getattr 并且我们似乎鼓励用户使用 getattr 而不是 hasattr,但实际上并不是因为性能?仅仅是因为它更pythonic吗?
也许我在测试中做错了什么:)
谢谢,
劳尔
【问题讨论】:
-
这里的区别不是性能。你说的是5纳秒。仅使用 Python,您就会损失数千倍。这里的区别在于哪一个对你需要做的事情是正确的。
-
性能差异不是重点。我不明白为什么文档中的注释说明它是通过调用 getattr 实现的。
-
也许在某一时刻它确实调用了
getattr,但现在它没有,但没有人更新文档......?不过,坦率地说,这种声明无论如何都不属于 API 文档。文档应该解释发生了什么,而不是如何发生,除非“如何”是“什么”的重要组成部分。
标签: python python-2.7 python-3.x cpython