It depends. A little.
For trivial cases, I'll often keep an else
for obvious parallelism:
def foo(arg1, arg2):
if condition:
return arg1
else:
return arg2
But for anything that gets remotely complicated, I'll drop the else
, and generally advise others do the same. This is because it's really difficult to follow a function like this:
def foo():
if cond1:
# ten lines here
return value
else:
if cond2:
# another ten lines
return value
else:
if cond3:
# ten more lines
return value
# ...a couple dozen lines here...
return value
Say I want to refactor this function, or some code that uses it, and I want to know how exactly the return value is computed because someone forgot to write documentation. The first thing I see is three separate if
s all with a bunch of code in them, and now it looks like there are eight different combinations of things that might have happened to value
, and who knows how many paths to each return
and I sigh and take a swig of vodka and go to figure out what they all are.
Worse, imagine if each of those if
blocks only conditionally does a return
.
On the other hand, this is pretty easy to follow even with many more conditions:
def foo():
if cond1:
# ten lines here
return value
if cond2:
# another ten lines
return value
if cond3:
# ten more lines
return value
# ...a couple dozen lines here...
return value
How many ways can this go? Four, and they're clearly intended to be mutually exclusive, and the return
s even line up visually.
Nested blocks read like exponential complexity. Sequential blocks read like a series of steps, which is more like what you intend to convey.
Ultimately I think keeping your return
s outdented as far as possible is a good compromise with the spirit of the Single Return Principle, which I've otherwise never bothered to follow.
And yes, I've refactored code like this :)