56

It's very common in C: hacking 'empty if statement' like this:

if(mostlyhappencondition)
    ;#empty statement
else{
    dosomething;
}

Is it working in Python? I mean, can we improve the application's performance by using that? I'd also like to know why.

5
  • 4
    It's common in C? It looks like a misguided attempt at optimization to me. Commented Feb 28, 2013 at 12:48
  • 3
    I was looking for similar coding strategy. The reason is not for optimization but for better readability of the code. Like instead of using if not some_thing and not some_thing_else: do_something its better to read code as if something or something_else: pass else: do_something. The answers here helped! Thanks. Commented May 15, 2016 at 23:01
  • 4
    even more useful when you just want to put an empty # TODO block Commented Jan 21, 2020 at 3:30
  • I can imagine a better readability case when a number of things is tested (validated) in if-elif[-...]-else block like in if some-long-condition: pass elif one-more-long-condition: pass [elif ...] else: return (exit function with) something-like-abrupt-error-message somewhat similar to what @SourabhBhat- shared. It would be much more convenient than negating the conditions to return something-like-abrupt-error-message each and every if or elif. Commented Sep 19, 2022 at 21:11
  • The case I explain above seems to me a kind of other languages' switch-case construct with empty broken cases (cases with breaks) and one-for-all default substitute. Commented Sep 19, 2022 at 21:19

4 Answers 4

61

There is a performance improvement if there isn't an else case in the "if", since the bytecodes don't pass execution into the "if" case.

Here are some functions and the output of dis.dis(foo).

The following sample application:

def foo(x):
    if x:
        pass
    else:
        return x+2

Disassembles to:

5           0 LOAD_FAST                0 (x)
            3 POP_JUMP_IF_FALSE        9

6           6 JUMP_FORWARD             8 (to 17)

8     >>    9 LOAD_FAST                0 (x)
           12 LOAD_CONST               1 (2)
           15 BINARY_ADD
           16 RETURN_VALUE
      >>   17 LOAD_CONST               0 (None)
           20 RETURN_VALUE

The following

def foo(x):
    if not x:
        return x+2

Disassembles to:

11           0 LOAD_FAST                0 (x)
             3 POP_JUMP_IF_TRUE        14

12           6 LOAD_FAST                0 (x)
             9 LOAD_CONST               1 (2)
            12 BINARY_ADD
            13 RETURN_VALUE
       >>   14 LOAD_CONST               0 (None)
Sign up to request clarification or add additional context in comments.

3 Comments

it's a pretty stupid compiler if it is not able to recognize if an if / else has no code and is just to document code. I hope Python has solved this bug.
I mean, pass isn't really "no code". It is a keyword. But I don't think it does much other than... well... pass, :D. Likely just an unhandled edge case. Is it a bug? I wouldn't say so.
Answer outdated - this disassembly is no longer correct for recent Python versions. And there is no performance improvement, they're the same within margin of error.
34

I can only guess you're looking for the pass statement, sometimes needed to create an empty code block to prevent a syntax error.

if mostlyhappencondition:
    pass
else:
    do_something()

It would be much more usual to just do this, which is logically equivalent:

if not mostlyhappencondition:
    do_something()

There are no significant performance gains to be found here.

1 Comment

There are intelligibility gains when using spectific if/elif/else or try/except.
4

Till the time you dont have any thing in if True: you could do

if not mostlyhappenedcondition:
   do something()

If you dont have to put any thing in "if" even in future, then it is redundunt in your code.

Comments

3

No, that won’t improve performance. In fact, it doesn’t in C, either. Where did you hear that?

not/! reads better and should have more or less the same speed.


And actually tested with gcc -O4:

#include <stdio.h>

int main(int argc, char *argv[]) {
    for(int i = 0; i < 1000000000; i++) {
        if(!(i < 900000000)) {
            putchar('.');
        }
    }
}

vs.

#include <stdio.h>

int main(int argc, char *argv[]) {
    for(int i = 0; i < 1000000000; i++) {
        if(i < 900000000);
        else {
            putchar('.');
        }
    }
}

#1 took 6.62 seconds and #2 took 6.64 seconds on my computer.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.