# [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

```