Imr*_*ran 80 python attributes exception-handling exception hasattr
if hasattr(obj, 'attribute'):
# do somthing
Run Code Online (Sandbox Code Playgroud)
VS
try:
# access obj.attribute
except AttributeError, e:
# deal with AttributeError
Run Code Online (Sandbox Code Playgroud)
哪个应该是首选,为什么?
小智 84
任何说明性能差异的长凳?
这是你的朋友
$ 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
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 79
hasattr内部并快速执行与try/except块相同的任务:它是一个非常具体,优化的单任务工具,因此在适用时应优先选择通用的替代方案.
poo*_*lie 20
还有第三种,通常更好的替代方案:
attr = getattr(obj, 'attribute', None)
if attr is not None:
print attr
Run Code Online (Sandbox Code Playgroud)
好处:
getattr没有马丁盖泽指出的不良异常 - 吞咽行为 - 在古老的蟒蛇中,hasattr甚至会吞下一个KeyboardInterrupt.
您正在检查对象是否具有属性的正常原因是您可以使用该属性,这自然会导致它.
该属性以原子方式读取,并且对于更改对象的其他线程是安全的.(但是,如果这是一个主要问题,您可能需要考虑在访问它之前锁定对象.)
它比短于try/finally和短于hasattr.
除了您期望的那个之外,一个广泛的except AttributeError区块可以捕获AttributeErrors,这可能导致混乱的行为.
访问属性比访问本地变量要慢(特别是如果它不是普通的实例属性).(虽然,老实说,Python中的微优化通常是一个愚蠢的错误.)
需要注意的一件事是,如果你关心obj.attribute设置为None的情况,你需要使用不同的sentinel值.
Mar*_*ler 17
我几乎总是使用hasattr:对于大多数情况来说,这是正确的选择.
有问题的情况是当一个类重写时__getattr__:hasattr将捕获所有异常而不是AttributeError像你期望的那样捕获.换句话说,b: False即使查看ValueError异常更合适,下面的代码也会打印出来:
class X(object):
def __getattr__(self, attr):
if attr == 'a':
return 123
if attr == 'b':
raise ValueError('important error from your database')
raise AttributeError
x = X()
print 'a:', hasattr(x, 'a')
print 'b:', hasattr(x, 'b')
print 'c:', hasattr(x, 'c')
Run Code Online (Sandbox Code Playgroud)
因此重要的错误就消失了.这已在Python 3.2(issue9666)中修复,hasattr现在只能捕获AttributeError.
一个简单的解决方法是编写如下的实用程序函数:
_notset = object()
def safehasattr(thing, attr):
return getattr(thing, attr, _notset) is not _notset
Run Code Online (Sandbox Code Playgroud)
这让我们getattr处理这种情况,然后它可以提出适当的例外.
Roe*_*ler 13
我想说这取决于你的函数是否可以接受没有设计属性的对象,例如,如果你有两个函数调用者,一个提供一个具有属性的对象,另一个提供一个没有它的对象.
如果您获得没有该属性的对象的唯一情况是由于某些错误,我建议使用异常机制,即使它可能更慢,因为我相信它是一个更简洁的设计.
一句话:我认为这是设计和可读性问题,而不是效率问题.
如果没有属性不是错误条件,则异常处理变体有问题:它还会捕获访问 obj.attribute 时可能在内部出现的 AttributeErrors(例如,因为属性是一个属性,因此访问它会调用一些代码)。
这个题目是在EuroPython 2016报告涉及写作更快的Python塞巴斯蒂安Witowski。这是他的幻灯片的复制品和绩效总结。他还在讨论中使用了术语look before you jumping,这里值得一提的是标记该关键字。
如果该属性实际上缺失,那么请求宽恕将比请求权限慢。因此,根据经验,如果您知道很可能会丢失该属性或您可以预测的其他问题,则可以使用请求许可方式。否则,如果您期望代码将导致大多数时候可读的代码
# CASE 1 -- Attribute Exists
class Foo(object):
hello = 'world'
foo = Foo()
if hasatter(foo, 'hello'):
foo.hello
## 149ns ##
try:
foo.hello
except AttributeError:
pass
## 43.1 ns ##
## 3.5 times faster
# CASE 2 -- Attribute Absent
class Bar(object):
pass
bar = Bar()
if hasattr(bar, 'hello'):
bar.hello
## 428 ns ##
try:
bar.hello
except AttributeError :
pass
## 536 ns ##
## 25% slower
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28369 次 |
| 最近记录: |