Note: all of this code was run on my machine using Python 3.6.1. Not everything will work the same if you test using Python 2.
>>>a=42>>>b=42>>>aisbTrue>>>a=316>>>b=316>>>aisbFalse
That is suprising! It turns out that all “small integers” with the same value point to the same memory. We can use the Python built-in function id
which returns a value you can think of as a memory address to investigate.
>>>a=128>>>b=256>>>id(a)4504844960>>>id(b)4504849056>>>(id(a)-id(b))/(a-b)32.0
It looks like there is a table of tiny integers and each integer takes up 32 bytes.
>>>x=1000>>>y=2000>>>id(x)4508143344>>>id(y)4508143312>>>id(x)-id(y)32
It looks like integers that aren’t in the small integers table also take up 32 bytes. The id
for these is way larger than for the small integers which means they are stored somewhere else.
>>>id(x)-id(256)3294288
What happens if we change the value of an integer in this table? Python has a module called ctypes that can be misused to directly edit memory. (We could also use a debugger but this way all the examples are in Python.)
>>>importctypes>>>>>>defmutate_int(an_int,new_value):...ctypes.memmove(id(an_int)+24,id(new_value)+24,8)...>>>a_number=7>>>another_number=7>>>mutate_int(a_number,13)>>>a_number13>>>another_number13
Not only have we changed a_number
and another_number
but all new references to 7
:
>>>foriinrange(0,10):...print(i)...01234561389
Even doing math with 7
no longer works correctly 🎉
>>>713>>>6+113>>>7+114>>>(7+1)-113>>>7*226>>>0b1111^0b100013
P.S. You can read more about the table of small integers in the CPython source code.