Why is local variable access faster than class access in Python?

When trying to solve a more complicated problem, I came to compare access speed with vs member local variables.

Here's the test program:

#!/usr/bin/env python MAX=40000000 class StressTestMember(object): def __init__(self): self.m = 0 def do_work(self): self.m += 1 self.m *= 2 class StressTestLocal(object): def __init__(self): pass def do_work(self): m = 0 m += 1 m *= 2 # LOCAL access test for i in range(MAX): StressTestLocal().do_work() # MEMBER access test for i in range(MAX): StressTestMember().do_work() 

I know that it might seem like a bad idea to instantiate StressTestMember and StressTestLocal at each iteration, but that makes sense in a simulated program where they are mostly active records.

After a simple test

  • Local Access Test: 0m22.836
  • MEMBER Access Check: 0m32.648s

The local version is ~ 33% faster, although part of the class. Why?

+8
performance python benchmarking
source share
2 answers

self.m += 1 means that you need to find a local variable called self , and then find the attribute m

Of course, if you just need to find a local variable, it will be faster without an extra step.

It may be useful to see what happens under the hood:

 >>> import dis >>> dis.dis(StressTestLocal.do_work) 18 0 LOAD_CONST 1 (0) 3 STORE_FAST 1 (m) 19 6 LOAD_FAST 1 (m) 9 LOAD_CONST 2 (1) 12 INPLACE_ADD 13 STORE_FAST 1 (m) 20 16 LOAD_FAST 1 (m) 19 LOAD_CONST 3 (2) 22 INPLACE_MULTIPLY 23 STORE_FAST 1 (m) 26 LOAD_CONST 0 (None) 29 RETURN_VALUE >>> dis.dis(StressTestMember.do_work) 10 0 LOAD_FAST 0 (self) 3 DUP_TOP 4 LOAD_ATTR 0 (m) 7 LOAD_CONST 1 (1) 10 INPLACE_ADD 11 ROT_TWO 12 STORE_ATTR 0 (m) 11 15 LOAD_FAST 0 (self) 18 DUP_TOP 19 LOAD_ATTR 0 (m) 22 LOAD_CONST 2 (2) 25 INPLACE_MULTIPLY 26 ROT_TWO 27 STORE_ATTR 0 (m) 30 LOAD_CONST 0 (None) 33 RETURN_VALUE 
+19
source share

Local names are faster because Python does some optimization so that local names do not need type access, on the other hand, instance attributes must have access to the __dict__ object.

This is also the reason local names are faster than global names.

+5
source share

All Articles