Why is the id of a Python class not unique when called quickly?

The id of an object is only guaranteed to be unique during that object’s lifetime, not over the entire lifetime of a program. The two someClass objects you create only exist for the duration of the call to print – after that, they are available for garbage collection (and, in CPython, deallocated immediately). Since their lifetimes don’t overlap, it is valid for them to share an id.

It is also unsuprising in this case, because of a combination of two CPython implementation details: first, it does garbage collection by reference counting (with some extra magic to avoid problems with circular references), and second, the id of an object is related to the value of the underlying pointer for the variable (ie, its memory location). So, the first object, which was the most recent object allocated, is immediately freed – it isn’t too surprising that the next object allocated will end up in the same spot (although this potentially also depends on details of how the interpreter was compiled).

If you are relying on several objects having distinct ids, you might keep them around – say, in a list – so that their lifetimes overlap. Otherwise, you might implement a class-specific id that has different guarantees – eg:

class SomeClass:
    next_id = 0

    def __init__(self):
         self.id = SomeClass.nextid
         SomeClass.nextid += 1

Leave a Comment