First of all, like all the coding zen statements, the forgiveness vs permission principle is not an absolute one. In this case in particular you know for sure that the first that will happen inside the try/except
block is the raise of the AttributeError
, but you might find yourself in situations where the AttributeError
is raised after additional operations that are costly or have side effects.
def some_function(foo):
costly_operation()
insert_something_to_a_database(foo)
return foo.bar + foo.baz
try:
some_function(foo)
except AttributeError:
# All the work done was not needed and it may even have
# left traces (like the db insert) that now need to be undone.
In these cases, it is simpler, safer more readable and more efficient to check for permission before executing anything rather than performing unneeded operations or even trying to fix the mess afterwards.
If, anyways, you really need to ask for forgiveness rather than permission you can simply check for permission afterwards: You go ahead assuming that everything is right and, if there is an error, you figure out if it was the one that you want to raise or not.
try:
some_function(foo)
except AttributeError:
if not hasattr(foo, 'bar'):
raise