Gustavo Sutter
Gustavo Sutter

Reputation: 94

Why Python works faster when declaring integer variable with int()?

While programming a algorithm that makes use of only using integer arithmetic I notice that Python wasn't taking advantage of it.

So I tried the following code to see the "explicitly" declaration effect

import time

repeat = 1000000

start = time.time()
x = 0
for i in range(repeat):
    x += 1
no_type_time = time.time() - start

start = time.time()
y = int(0)
for i in range(repeat):
    y += 1
int_time = time.time() - start

print('{} - No type'.format(no_type_time))
print('{} - Int'.format(int_time))

The code output was the following:

0.0692429542542 - No type
0.0545210838318 - Int

I assume it has something to do with Python being a dynamic typed language. But when I try to find out the type of the variables, using type(x) and type(y) both output int. Which is curious, because I also ran some tests using x = float(0) and the result is very close to the one with no type "declaration".

I'd like to know why it happens and if possible to get some reference from Python documentation explaining it.

Upvotes: 0

Views: 2166

Answers (3)

user2357112
user2357112

Reputation: 280973

From the precision on the floats in your str.format output (12 significant digits), we can see that you're probably on Python 2.

Python 2 creates an explicit list of a million ints when you run range(repeat), which is slow. It also keeps the memory for all of those ints, so range(repeat) is less slow the second time. This is most likely the source of the timing difference, not anything to do with calling int.

On Python 2, it is almost always better to use xrange instead of range. xrange generates ints on demand, avoiding the cost in memory and allocation time of generating a whole list up front:

for i in xrange(repeat):
    do_stuff()

Upvotes: 7

Brendan Abel
Brendan Abel

Reputation: 37539

This is happening because python caches and reuses some immutable built-in objects, even if they're "stored" as different variables

>>> a = 1
>>> id(a)
56188528L
>>> b = int(1)
>>> id(b)
56188528L

Python didn't have to allocate any memory or instantiate a new object for the second variable. It's just reusing the immutable integer object that had already been created.

If you had put your timing tests in different files and ran them separately, or if you had ran the int(1) test first, you would have seen different results.

Upvotes: -1

KarlR
KarlR

Reputation: 1615

I am not able to reproduce on linux. Mark that:

• real: The actual time spent in running the process from start to finish, as if it was measured by a human with a stopwatch

• user: The cumulative time spent by all the CPUs during the computation

• sys: The cumulative time spent by all the CPUs during system-related tasks such as memory allocation.

→ time python type.py

real    0m0.219s
user    0m0.000s
sys     0m0.000s

→ time python without_type.py

real    0m0.133s
user    0m0.000s
sys     0m0.000s

Upvotes: 1

Related Questions