Integer Interning in Python (Optimization)

Interning is an optimization technique by making global cache of particular objects in memory as they are instantiated. It is basically reusing objects on-demand.


In Python optimization, integer interning is the method of caching or pre-loading a list of integers at start up.


Standard implementation of Python (CPython) pre-loads (caches) a global list of integers in the range from -5 to 256. Any time an integer is referenced in this range Python does not create new one but uses the cached version. This is known as integer interning.

To understand concept of integer interning, let's check memory address of integers inside & outside of the range -5 to 256:

Address of Integer Inside Range (-5 to 256)


# Integer interning

x = 20
y = 20

print("Address of x: ", id(x))
print("Address of y: ", id(y))

Output

Address of x:  140719184847856
Address of y:  140719184847856

Address of both integer x & y are same. Here integer object <20> is same but used by two references x & y. Here, Python has to point the existing reference for 20.

Address of Integer Outside Range (-5 to 256)



x = 257
y = 257

p = -6
q = -6

print("Address of x: ", id(x))
print("Address of y: ", id(y))
print()
print("Address of p: ", id(p))
print("Address of q: ", id(q))

Output

Address of x:  1744668315824
Address of y:  1744668316176

Address of p:  1744668315760
Address of q:  1744668316112

Address of x & y are different. And similarly, address of p & q are also different. In these scenario, Python does not use that global cached list and a new object is created every time.

Why Does Python Intern?

This is basically an optimization techniques in Python. Since small integers are relatively used more in our code than large integers. So Python decides to pre-cache certain range (-5 to 256) of integers for performance reason.

Why not to intern everything?

Answer is performance & memory overhead. Interning everything requires a lot of memory & start up may take long since interning occurs at start up time.

So question of what to intern & what not to intern is kind of trade-off. We choose that range of an integer in interning which has higher reusability.

Way of Creating Object Doesn't Affect Interning

No matter how you create integer object, if it is same and within range (-5 to 256) it will be interned. See code example below:


a = 100 # direct integer assignment
b = int(100) # using int() built-in function
c = int('100') # Converting string to inetegr
d = int('1100100', 2) # From binary to integer, 2 indicates base for number system

print("Value:")
print("a = ", a, " b = ", b, " c = ", c, " d = ", d)
print("---------")
print("Address:")
print("a = ", id(a), " b = ", id(b), " c = ", id(c), " d = ", id(d))

Output

Value:
a =  100  b =  100  c =  100  d =  100
---------
Address:
a =  140719184850416  b =  140719184850416  c =  140719184850416  d =  140719184850416

Note that all Addresses are same.


Extra Note

Integers from -5 to 256 are known as singleton objects (classes that can be instantiated only once) in standard implementation of Python.