Python: multiple assignment vs. individual assignment speed
Asked Answered
F

2

11

I've been looking to squeeze a little more performance out of my code; recently, while browsing this Python wiki page, I found this claim:

Multiple assignment is slower than individual assignment. For example "x,y=a,b" is slower than "x=a; y=b".

Curious, I tested it (on Python 2.7):

$ python -m timeit "x, y = 1.2, -1.4"
10000000 loops, best of 3: 0.0365 usec per loop

$ python -m timeit "x = 1.2" "y = -1.4"
10000000 loops, best of 3: 0.0542 usec per loop

I repeated several times, in different orders, etc., but the multiple assignment snippet consistently performed at least 30% better than the individual assignment. Obviously the parts of my code involving variable assignment aren't going to be the source of any significant bottlenecks, but my curiousity is piqued nonetheless. Why is multiple assignment apparently faster than individual assignment, when the documentation suggests otherwise?

EDIT:

I tested assignment to more than two variables and got the following results:

The trend seems more or less consistent; can anyone reproduce it?

(CPU: Intel Core i7 @ 2.20GHz)

Froemming answered 9/3, 2014 at 5:15 Comment(4)
With Python 2.7.5 I don't see results which agree with yours. I see multiple assigment @ 0.0494 usec/loop and individual assignment @ 0.0452 usec/loop.Keratinize
Python 2.7.4 Ubuntu 13.04 here. I am able to reproduce the problem and in Python 3.3.2, I am not.Ampereturn
Python 2.7.6 gives similar findings like OP. Python 3.3 gives a bit more close (0.49 & 0.55) readings.Sheply
362 vs 453 in Python 2.7.3. I see no difference on Python 3.4 ~250Streamliner
N
4

Interestingly, it may depend on the CPU to some extent. These are both 64 bit linux machines (same Python build).

Result for Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz

$ python -V
Python 2.7.5+
$ python -m timeit "x, y = 1.2, -1.4"
10000000 loops, best of 3: 0.0554 usec per loop
$ python -m timeit "x = 1.2" "y = -1.4"
10000000 loops, best of 3: 0.0349 usec per loop

Result for Intel(R) Pentium(R) CPU G850 @ 2.90GHz

$ python -V
Python 2.7.5+
$ python -m timeit "x, y = 1.2, -1.4"
10000000 loops, best of 3: 0.0245 usec per loop
$ python -m timeit "x = 1.2" "y = -1.4"
10000000 loops, best of 3: 0.0394 usec per loop
Normalcy answered 9/3, 2014 at 5:28 Comment(0)
A
1

Better look at dis module of python. Which disassembles bytecode. The test shows on two variable assignment:

import dis 

def single_assignment():
    x = 1 
    y = 2 

def multiple_assignment():
    x, y = 1, 2

print dis.dis(single_assignment)
print dis.dis(multiple_assignment)

Bytecode:

  4           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)

  5           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (y)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        
None
  8           0 LOAD_CONST               3 ((1, 2))
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               0 (x)
              9 STORE_FAST               1 (y)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        
None

It looks number of bytecode required is same in case of 2 variables. If there's 3 or more variable assignment, number of bytecode is smaller.

Apprise answered 9/3, 2014 at 5:29 Comment(3)
Number of bytecode instructions is not a good indicator of performance.Spectrometer
I could've sworn this was one of the cases the peephole optimizer was supposed to catch.Siclari
This shows that using constants is not the best test; the test should be done using variables instead; x, y = a, b, not x, y = 1, 2. Oh, and dis.dis() already uses print, and returns None; remove your prints from your script here.Marijn

© 2022 - 2024 — McMap. All rights reserved.