hasattr()vs try except块处理不存在的属性

2024-04-24 06:26:24 发布

您现在位置:Python中文网/ 问答频道 /正文

if hasattr(obj, 'attribute'):
    # do somthing

try:
    # access obj.attribute
except AttributeError, e:
    # deal with AttributeError

应该选择哪个,为什么?


Tags: objifaccesswithattributedohasattrattributeerror
3条回答

还有第三种选择,而且往往更好:

attr = getattr(obj, 'attribute', None)
if attr is not None:
     print attr

优点:

  1. getattr没有坏的exception-swallowing behavior pointed out by Martin Geiser-在老Python中,hasattr甚至会吞下KeyboardInterrupt

  2. 检查对象是否具有属性的正常原因是可以使用该属性,这自然会导致该属性。

  3. 该属性以原子方式读取,并且可以防止其他线程更改对象。(不过,如果这是一个主要问题,您可能需要考虑在访问对象之前将其锁定。)

  4. 它比try/finally短,而且通常比hasattr短。

  5. 一个广泛的except AttributeError块可以捕获比您期望的AttributeErrors块更多的except AttributeError,这可能导致混乱的行为。

  6. 访问一个属性比访问一个局部变量慢(特别是如果它不是一个普通的实例属性)。(不过,老实说,Python中的微优化通常是一件傻事。)

需要注意的一点是,如果您关心将obj.attribute设置为None的情况,则需要使用不同的sentinel值。

有什么长椅能说明性能的不同吗?

时间是你的朋友

$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "nonexistent")'
1000000 loops, best of 3: 1.87 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "a")'
1000000 loops, best of 3: 0.446 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.a
except:
 pass'
1000000 loops, best of 3: 0.247 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.nonexistent
except:
 pass'
100000 loops, best of 3: 3.13 usec per loop
$

       |positive|negative
hasattr|  0.446 |  1.87 
try    |  0.247 |  3.13

hasattr在内部快速地执行与try/except块相同的任务:它是一个非常特定、优化的单任务工具,因此在适用时,应该首选非常通用的替代工具。

相关问题 更多 >