Basic question about speed/coding style/memory

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Jul 21 11:06:40 CEST 2012


On Sat, 21 Jul 2012 10:33:27 +0300, Jan Riechers wrote:

> Hello Pythonlist,
> 
> I have one very basic question about speed,memory friendly coding, and
> coding style of the following easy "if"-statement in Python 2.7, but Im
> sure its also the same in Python 3.x

I assume that the following is meant to be inside a function, otherwise 
the return in the second example is illegal.

But in general, you're worrying too much about trivia. One way or the 
other, any speed difference will be trivial. Write whatever style reads 
and writes most naturally, and only worry about what's faster where it 
actually counts.

To give it an analogy that might be clear, this question is not too far 
from worrying about whether your car will be faster with the radio aerial 
up or down. Yes, technically the car will be slower with the aerial up, 
due to air resistance, but you'd have a job measuring it, and it makes no 
difference whether you are zooming down the highway at 120mph or stuck in 
traffic crawling along at 5mph.


Here's a minimal example:


def with_else(x):
    if x:
        a = x
    else:
        a = x+1
    return a


def without_else(x):
    if x:
        a = x
        return a
    a = x+1
    return a


Notice that I try to make each function do the same amount of work, so 
that we're seeing only the difference between "else" vs "no else".

Now let's test the speed difference with Python 2.7. Because this is 
timing small code snippets, we should use the timeit module to time the 
code:

from timeit import Timer
setup = "from __main__ import with_else, without_else"
t1 = Timer("for i in (0, 1): result = with_else(i)", setup)
t2 = Timer("for i in (0, 1): result = without_else(i)", setup)

Each snippet calls the function twice, once to take the if branch, then 
to take the else branch.

Now we time how long it takes to run each code snippet 1000000 times. We 
do that six times each, and print the best (lowest) speed:

py> min(t1.repeat(repeat=6))
0.9761919975280762
py> min(t2.repeat(repeat=6))
0.9494419097900391

So there is approximately 0.03 second difference per TWO MILLION 
if...else blocks, or about 15 nanoseconds each. This is highly unlikely 
to be the bottleneck in your code. Assuming the difference is real, and 
not just measurement error, the difference is insignificant.

So, don't worry about which is faster. Write whichever is more natural, 
easier to read and write.


> Block
> #----------------------------------
> if statemente_true:
> 	doSomething()
> else:
> 	doSomethingElseInstead()

This style is especially recommended when the two clauses are equal in 
importance.


> versus this block:
> #----------------------------------
> if statement_true:
> 	doSomething()
> 	return
> doSomethingElseInstead()

This style is especially recommended when the doSomethingElseInstead() 
block is the "normal" procedure, and the doSomething() block is a special 
case. Not necessarily rare, but nevertheless special in some sense.

Of course, the decision as to which is the "special" case and which is 
the "normal" case is often entirely arbitrary.



-- 
Steven



More information about the Python-list mailing list