225

Suppose I have an if statement with a return. From the efficiency perspective, should I use

if(A > B):
    return A+1
return A-1

or

if(A > B):
    return A+1
else:
    return A-1

Should I prefer one or another when using a compiled language (C) or a scripted one (Python)?

Jorge Leitao
  • 19,085
  • 19
  • 85
  • 121
  • 17
    In a compiled language you don't need to worry about efficiency much. The compiler sorts that out. You should write your code so you can read it. (You still have to worry about the efficiency of your algorithms, and sloppy use of types etc. will affect efficiency - you just don't have worry about your style too much.) I don't know about Python though. – ams Feb 08 '12 at 11:58
  • 5
    Relying on your compiler to sort out your code is a dangerous step - and requires an infallible compiler. Better if you know whay tou want your code to do! – Andrew Jul 04 '13 at 21:05
  • 1
    If what you are doing is defined by the spec, then i do not believe there is any reason to doubt the compiler. It will have been written be people far smarter than you, and it's far more likely that you made a mistake than them. – will Oct 30 '14 at 16:02
  • 12
    How can this be closed for opinion based? It may be an opinion *after* you know that there is no performance difference between the two. I did not, and I am pretty sure that a lot of people also did not. – Jorge Leitao Nov 13 '16 at 06:47
  • 2
    While the question is quite popular, it can't be answered accurately without a specific language in mind, or otherwise, answering for every languages would be too long for this format. – Emile Bergeron Nov 14 '16 at 02:12
  • @EmileBergeron: the relevant tags for languages were removed in an edit for some reason. I added them back and updated the question respectively. Please also see http://meta.stackoverflow.com/q/337800/931303 – Jorge Leitao Nov 14 '16 at 09:35
  • @EmileBergeron actually, language doesn't matter. The compiler/interpreter, on the other hand, does. – Braiam Nov 14 '16 at 11:22
  • 1
    @Braiam I agree, but before we talk about a compiler/interpreter, we need to decide on which language we want to discuss. – Emile Bergeron Nov 14 '16 at 13:45
  • 1
    As replied by @ams , Usually you don't need to focus much on optimizations. Furthermore, preemptive optimization is considered a bad practice. “It is far, far easier to make a correct program fast than to make a fast program correct.” – Herb Sutter https://hygger.io/blog/programming-quotes-42/ – percebus Nov 27 '18 at 23:05

9 Answers9

277

Since the return statement terminates the execution of the current function, the two forms are equivalent (although the second one is arguably more readable than the first).

The efficiency of both forms is comparable, the underlying machine code has to perform a jump if the if condition is false anyway.

Note that Python supports a syntax that allows you to use only one return statement in your case:

return A+1 if A > B else A-1
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 39
    C supports that too. `return (A>B)?A+1:A-1;` However there is _absolutely no gain in performance_ from writing the code like this. All we have achieved is to make the code obfuscated, unreadable and in some cases more vulnerable to implicit type promotions. – Lundin Feb 08 '12 at 10:51
  • 62
    @Lundin obfuscated? unreadable? Only for those who don't know the ternary operator. – glglgl Feb 08 '12 at 11:23
  • Ok, I understand that. My point is that different things happens when the language is compiled or interpreted. As @ams pointed out on a comment, compiler does have an influence on the performance. Can you add to this answer some information on that so I can accept it? – Jorge Leitao Feb 08 '12 at 12:09
  • @J.C.Leitão, well, Python code is usually compiled to intermediate language code (depending on the implementation), so ams's comment does apply here: you shouldn't worry too much about style. – Frédéric Hamidi Feb 08 '12 at 12:32
  • 6
    @Lundin Following this argumentation, `<` is bad practice because `-1 < 1u` produces an unexpected result. – glglgl Feb 08 '12 at 15:42
  • 3
    @glglgl: No, because people expect the ?: operator to behave as if-else, which isn't true. If somebody would write code like `-1 < 1u`, which I doubt, they would easily spot the bug. Quite a lot of people would write some version of the code I posted however. I have seen such bugs far too often in production code to trust the ?: operator. Also as a rule of thumb, if the language gives you two different ways to do the same thing, only use one of them, don't randomly pick either of the two depending on your mood. – Lundin Feb 09 '12 at 12:11
  • 6
    @Lundin that is an argument for being careful with ?: in C, but you seem to be saying it applies to Python as well. Can you point to any examples where using the ternary in Python leads to unexpected results? – lvc Feb 10 '12 at 02:23
  • 1
    @lvc No, I have no idea of how Python handles implicit type promotions in various operators. – Lundin Feb 10 '12 at 07:36
  • 1
    @Lundin python is duck-typed so there is no such thing as "implicit type promotion". Operators are implemented as special methods by the nearest (via MRO) abstract class that defines the type. – cowbert Mar 14 '18 at 07:51
56

From Chromium's style guide:

Don't use else after return:

# Bad
if (foo)
  return 1
else
  return 2

# Good
if (foo)
  return 1
return 2

return 1 if foo else 2
skeller88
  • 4,276
  • 1
  • 32
  • 34
  • 2
    Thanks. +1. May I ask why don't use else after return? – Tim Jun 18 '17 at 20:38
  • 1
    if-else is functionally equivalent, but it's verbose. The else is unnecessary. – skeller88 Jun 18 '17 at 20:43
  • 35
    I was surprised because the first seems more clear and thus better. – Tim Jun 18 '17 at 20:44
  • 9
    You could make a reasonable case for either. The most important thing in this decision IMO is to be consistent within the code base. – skeller88 Jun 18 '17 at 20:46
  • What about ensuring clean branch coverage in testing? The lack of the `else` still leaves it implicit making unit testing less clear, right? – iJames Mar 26 '18 at 19:19
  • That's an interesting point. I'm not sure how various test coverage checking software will handle one format vs. the other. Like I said, I have no strong preference since they have similar performance. The first case is more verbose but judging by the comments on this SO thread, more readable. The second case is recommended by Chromium, which means maybe more developers will recognize that format. More important than either option is being consistent in a code base. – skeller88 Mar 26 '18 at 21:20
  • 2
    you'll probably find in the majority of cases that `if-else-return` branches are almost never equal (if they are, then you should be refactoring anyway; either using a `switch` construct or for Python, enumerating a dict/using a callable/etc.). Therefore almost all `if-else-return` are cases of guard clauses and those are always testable (mock the tested expression) without the `else`. – cowbert Mar 28 '18 at 03:22
  • In Python, you could put a blank line in place of the `else`, then it will match the *good* solution, and be readable too. – c z May 31 '19 at 08:56
  • 1
    @cz Where's a link to that style? – skeller88 Jun 02 '19 at 03:14
  • 7
    I don't buy it. Reading one word 'else' is way more brain efficient than to mentally figure it out what's going on. Even if it's obvious. One word: 'else' will always be more obvious. Psychology 101 – cikatomo Feb 16 '21 at 17:19
13

I personally avoid else blocks when possible. See the Anti-if Campaign

Also, they don't charge 'extra' for the line, you know :p

"Simple is better than complex" & "Readability is king"

delta = 1 if (A > B) else -1
return A + delta
percebus
  • 799
  • 1
  • 8
  • 21
  • 4
    Why the down vote? Is a 'pythonic' answer. You might not consider it a preferred answer. But is not an invalid one. I am also following the KISS Principle https://en.wikipedia.org/wiki/KISS_principle – percebus Nov 27 '18 at 22:54
  • 3
    I upvoted your answer since for me it scores on readability and simple. I personally find it offensive is someone down-votes me without educating me on why my answer is actively negative. – Stephen Ellwood Nov 29 '18 at 12:56
  • 1
    Did not hear before about the Anti-if campaign but can understand why ifs can be dangerous. I always try to limit the amount of code enclosed by an if statement and try to rewrite elif trees to use dict. This is getting a bit off-topic though. – Stephen Ellwood Nov 29 '18 at 13:02
  • 1
    @StephenEllwood Using `dict`s to avoid diffs is a very bad idea performance-wise. – Bachsau Oct 06 '19 at 04:21
  • @Bachsau You are probably right. I've never had to worry about performance as all my scripts run in seconds. For me readability usually trumps performance. Since I'm not a full time programmer; they are just a means to an end. – Stephen Ellwood Oct 07 '19 at 22:10
8

Regarding coding style:

Most coding standards no matter language ban multiple return statements from a single function as bad practice.

(Although personally I would say there are several cases where multiple return statements do make sense: text/data protocol parsers, functions with extensive error handling etc)

The consensus from all those industry coding standards is that the expression should be written as:

int result;

if(A > B)
{
  result = A+1;
}
else
{
  result = A-1;
}
return result;

Regarding efficiency:

The above example and the two examples in the question are all completely equivalent in terms of efficiency. The machine code in all these cases have to compare A > B, then branch to either the A+1 or the A-1 calculation, then store the result of that in a CPU register or on the stack.

EDIT :

Sources:

  • MISRA-C:2004 rule 14.7, which in turn cites...:
  • IEC 61508-3. Part 3, table B.9.
  • IEC 61508-7. C.2.9.
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 45
    Are you sure the single-return religion has infected most coding standards? That would be frightening. – Daniel Fischer Feb 08 '12 at 10:52
  • 8
    I would say the rule doesn't make sense most of the time. I tend to find code more readable and easier to follow with returns at appropriate points. But that's just me. However, I thought of per company/project coding standards, not things like MISRA where otherwise idiotic prescriptions may occasionally have some merit. I hope most didn't buy into the single exit-point idea. – Daniel Fischer Feb 08 '12 at 13:33
  • 3
    @DanielFischer: In the C coding standard based on MISRA that I designed for my company, I have the rule "A function shall only have a single point of exit, at the end of the function, _unless_ a single point of exit makes the code less readable". So it is MISRA-C but with an exception to the rule. If you write an advanced parser function which can return lets say 10 differt errors, the level of nested braces make the code completely unreadable - in such a case it would be more sensible to return immediately as an error is encountered. – Lundin Feb 08 '12 at 15:37
  • That's okay. I think we'd (hypothetically) have some arguments over when the readability clause applies, but a reasonable compromise should be attainable. – Daniel Fischer Feb 08 '12 at 15:54
  • 6
    See [this SO question](http://stackoverflow.com/questions/4838828/why-should-a-function-have-only-one-exit-point) for a discussion and further links to further discussions on the single-exit-point issue. Besides the single-exit-point rule being old-fashioned and overly "engineeringy", Python *specifically* promotes a ["flat is better than nested" view](http://www.python.org/dev/peps/pep-0020/), and putting `return` **wherever** it happens to be clear is the idiomatic way to do it in Python. – John Y Jun 11 '13 at 13:55
  • I think that the fear of Cyclomatic Complexity is more a C/C++ phenomena than anything else https://en.wikipedia.org/wiki/Cyclomatic_complexity Single returns lead to nested if/else hell and are discouraged as anti-patterns. https://francescocirillo.com/pages/anti-if-campaign Lastly, in your example, you can reduce the confusion with if (A > B) { return A +1 } # implicit else return A -1 {code} – percebus Nov 27 '18 at 23:09
  • 1
    @percebus I completely agree and cyclomatic complexity is a good argument against single return. And I've been poking the MISRA committee about this several times, for example [see this](https://stackoverflow.com/a/42577015/584518). At least the rule got downgraded to advisory in MISRA-C:2012. – Lundin Apr 05 '19 at 06:45
5

With any sensible compiler, you should observe no difference; they should be compiled to identical machine code as they're equivalent.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

This is a question of style (or preference) since the interpreter does not care. Personally I would try not to make the final statement of a function which returns a value at an indent level other than the function base. The else in example 1 obscures, if only slightly, where the end of the function is.

By preference I use:

return A+1 if (A > B) else A-1

As it obeys both the good convention of having a single return statement as the last statement in the function (as already mentioned) and the good functional programming paradigm of avoiding imperative style intermediate results.

For more complex functions I prefer to break the function into multiple sub-functions to avoid premature returns if possible. Otherwise I revert to using an imperative style variable called rval. I try not to use multiple return statements unless the function is trivial or the return statement before the end is as a result of an error. Returning prematurely highlights the fact that you cannot go on. For complex functions that are designed to branch off into multiple subfunctions I try to code them as case statements (driven by a dict for instance).

Some posters have mentioned speed of operation. Speed of Run-time is secondary for me since if you need speed of execution Python is not the best language to use. I use Python as its the efficiency of coding (i.e. writing error free code) that matters to me.

Stephen Ellwood
  • 394
  • 1
  • 2
  • 11
  • 1
    If a user is going to down-vote my answer I would appreciate a comment as to why they thought I was wrong. – Stephen Ellwood Feb 17 '17 at 09:04
  • I would probably just a line before to make it 1 line per statement for readability purposes. `var n = 1 if (A > B) else -1` `return A+n` – percebus Jun 05 '17 at 14:30
  • @percebus in some cases I would agree if the variable name can enhance the meaning. For instance: 'code' move_x = 1 if my_x < opponent_x else -1 # move towards opponent – Stephen Ellwood Nov 26 '18 at 13:34
  • BTW I actually upvoted your answer. If you see my answer is rather similar – percebus Nov 27 '18 at 23:15
3

Version A is simpler and that's why I would use it.

And if you turn on all compiler warnings in Java you will get a warning on the second Version because it is unnecesarry and turns up code complexity.

juergen d
  • 201,996
  • 37
  • 293
  • 362
1

I know the question is tagged python, but it mentions dynamic languages so thought I should mention that in ruby the if statement actually has a return type so you can do something like

def foo
  rv = if (A > B)
         A+1
       else
         A-1
       end
  return rv 
end

Or because it also has implicit return simply

def foo 
  if (A>B)
    A+1
  else 
    A-1
  end
end

which gets around the style issue of not having multiple returns quite nicely.

Jamie Cook
  • 4,375
  • 3
  • 42
  • 53
-1

From a performance point of view, it doesn't matter in Python, and I'd assume the same for every modern language out there.

It really comes down to style and readability. Your second option (if-else block) is more readable than the first, and a lot more readable than the one-liner ternary operation.

Scarface97
  • 57
  • 1
  • 4