Why does the id function in Python return the same value for different integer objects?

Question:

I have a function to retrieve an object in Python using the ctypes module:

import ctypes

def object_at_addr(obj_addr):
    try:
        val = ctypes.cast(obj_addr, ctypes.py_object).value
    except:
        return None
    return val

I know that the id of an object shows the memory address the object is at (for the most part as far as I’ve seen with builtins and custom objects). On my terminal shell, I tried this on the number 0 and "recursively" found the id of each number to see if it was cyclic in some form. Here is the terminal output:

>>> id(0) # num1
4343595216
>>> id(4343595216) # num2
4344636112
>>> id(4344636112) # num3
4344636112 

To my surprise, the id of two numbers were the same. However, when I use my function and call object_at_addr(4344636112), it doesn’t point to either number, but instead returned a different int value as shown below:

>>> object_at_addr(4344636112)
4411205344

How can two different numbers have the same id value? Does the id function actually return the memory address for all objects, or is it only for custom objects, or is it just a Python design choice to make the memory address the id of an object, but it’s different for builtin objects?

Asked By: succulentz

||

Answers:

The id is always the memory address in the CPython implementation. The reason that you saw numbers with the same id here is that memory addresses can be re-used. The id is only guaranteed to be unique for the lifetime of the object, and since nothing else was holding a reference to the integer 4343595216 it got deleted immediately after the function call returns. That memory location was freed, and then immediately reused by the integer 4344636112 instance.

The docs actually mention this explicitly:

Two objects with non-overlapping lifetimes may have the same id() value.

Answered By: wim