这实际上取决于您认为将要抛出异常的频率。
在我看来,这两种方法至少在可读性和Python风格方面都同样有效。但是,如果90%的对象都没有该属性,则bar
您会注意到两种方法之间存在明显的性能差异:
>>> import timeit
>>> def askforgiveness(foo=object()):
... try:
... x = foo.bar
... except AttributeError:
... pass
...
>>> def askpermission(foo=object()):
... if hasattr(foo, 'bar'):
... x = foo.bar
...
>>> timeit.timeit('testfunc()', 'from __main__ import askforgiveness as testfunc')
2.9459929466247559
>>> timeit.timeit('testfunc()', 'from __main__ import askpermission as testfunc')
1.0396890640258789
但是,如果90%的对象确实具有属性,则表已被翻转:
>>> class Foo(object):
... bar = None
...
>>> foo = Foo()
>>> timeit.timeit('testfunc(foo)', 'from __main__ import askforgiveness as testfunc, foo')
0.31336188316345215
>>> timeit.timeit('testfunc(foo)', 'from __main__ import askpermission as testfunc, foo')
0.4864199161529541
因此,从性能的角度来看,您需要选择最适合您的情况的方法。
最后,对timeit
模块的某些战略性使用可能是您可以做的最Python化的事情。