[Tutor] Style question with classes and modules

Kent Johnson kent37 at tds.net
Thu Jul 19 22:27:54 CEST 2007


Tino Dai wrote:
>     Why do you expect a speedup?
> 
> 
> In the  Python  Reference by David Beazley on p. 40, he substituted 
> import math
> with from math import sqrt and he switched out d = d + math.sqrt(i) with
> sqrt(i). He said that that change made the program run twice as fast.  
> So therefore
> I was under the impression that "from somemodule import someclass" would 
> always be
> faster than import somemodule.

Attribute access is somewhat expensive so if you can pull it out of a
critical loop you get a speedup.
   import foo
   foo.bar()

and
   from foo import bar
   bar()

will not have an appreciable difference in speed. OTOH
   import foo
   for i in range(10000):
     foo.bar()
may be slower than
   from foo import bar
   for i in range(10000):
      bar()

because the attribute access is essentially being hoisted outside the
loop so it only happens once.

You can also get a speedup by putting a loop into a function so critical
variables are found in the local namespace instead of the module namespace.

Attribute lookup seems to have gotten better since Beazley wrote; here
is a test program that uses three ways to access math.sqrt - module
attribute, global name, local name. Note that in the third version, all
three names (sqrt, d, i) are local:

###########################
import math
from time import time

start = time()
d = 0.0
for i in xrange(1000000):
   d = d + math.sqrt(i)

duration = time() - start
print duration * 1000.

sqrt = math.sqrt

start = time()
d = 0.0
for i in xrange(1000000):
   d = d + sqrt(i)

duration = time() - start
print duration * 1000.

def compute():
     sqrt = math.sqrt
     d = 0.0
     for i in xrange(1000000):
       d = d + sqrt(i)

start = time()
compute()
duration = time() - start
print duration * 1000.
################################

Sample output:
745.465993881
561.167001724
369.343996048


Another way to measure this is with the timeit module:

kent $ python -m timeit -s "import math" "math.sqrt(1)"
1000000 loops, best of 3: 0.361 usec per loop
kent $ python -m timeit -s "from math import sqrt" "sqrt(1)"
1000000 loops, best of 3: 0.293 usec per loop

timeit runs both the setup code and the code under test inside a
function so all the names are local in this case.

Kent



More information about the Tutor mailing list