Short-circuiting and (and ==) instead of if in Python

& (verbiage overflow)Wed 01 May 2013RSS

Some people use a special short-circuiting and expression to replace if blocks in Python. For instance, instead of

if x >= 0.5:
    f(x)

one can use

x >= 0.5 and f(x)

The point is that because multi-term logical conditions are evaluated in series, f(x) is only evaluated after x >= 0.5 returns True, making x >= 0.5 a pre-condition of f(x).

You cannot use an outright assignment (here y = x) as the second part of the and statement; only a function will do.

In any case, this syntax is unsatisfying to me because it is less explicit than using if outright. But I've seen it defended by a gifted programmer as being "explicit once you recognize the syntax", and I wondered if there was any timing advantage to it.

The results of timing, on 10^8 iterations, are (in seconds):

time using if:  43.7663021088
time using and: 44.545058012

It doesn't look as though the and statement saves time, particularly. I suspect it is a case of coding craftiness — surely a pleasurable thing in itself. But it now seems clear to me that using if is better; it is both explicit and involves no loss of speed.


Addendum, later in the evening:

There is another way to use short-circuiting to avoid the use of if: with == instead of and; for instance:

x >= 0.5 == f(x)

Just as with and, == causes f(x) to be evaluated after x >= 0.5; we can show (though I have not done so here) that f(x) is in fact evaluated. But it turns out that this trick saves even less time:

time using ==:  50.7892489433

Best to stick with if, it seems.


The program I wrote to compare processing times follows:

import time
import random

def f(x):
    y = x
    rounds = 100000000
    r = random.random
    start_time = time.time()
    for i in xrange(rounds):
        x = r()
        if x >= 0.5:
            f(x)
    print 'time using if: ', time.time() - start_time
    start_time = time.time()
    for i in xrange(rounds):
        x = r()
        x >= 0.5 and f(x)
    print 'time using and:', time.time() - start_time
    start_time = time.time()
    for i in xrange(rounds):
        x = r()
        x >= 0.5 == f(x)
    print 'time using ==: ', time.time() - start_time

[end]

Comments are enabled.