It really depends on how often you think the exception is going to be thrown.
Both approaches are, in my opinion, equally valid, at least in terms of readability and pythonic-ness. But if 90% of your objects do not have the attribute bar
you'll notice a distinct performance difference between the two approaches:
>>> 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
But if 90% of your objects do have the attribute, the tables have been turned:
>>> 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
So, from a performance point of view, you need to pick the approach that works best for your circumstances.
In the end, some strategic use of the timeit
module may be the most Pythonic thing you can do.