Search code examples
pythonidentitycpythonpython-internals

Why does id({}) == id({}) and id([]) == id([]) in CPython?


Why does CPython (no clue about other Python implementations) have the following behavior?

tuple1 = ()
tuple2 = ()                                                                                                   
dict1 = {}
dict2 = {}
list1 = []
list2 = []
# makes sense, tuples are immutable
assert(id(tuple1) == id(tuple2))
# also makes sense dicts are mutable
assert(id(dict1) != id(dict2))
# lists are mutable too
assert(id(list1) != id(list2))
assert(id(()) == id(()))
# why no assertion error on this?
assert(id({}) == id({}))
# or this?
assert(id([]) == id([]))

I have a few ideas why it may, but can't find a concrete reason why.

EDIT

To further prove Glenn's and Thomas' point:

[1] id([])
4330909912
[2] x = []
[3] id(x)
4330909912
[4] id([])
4334243440

Solution

  • CPython is garbage collecting objects as soon as they go out of scope, so the second [] is created after the first [] is collected. So, most of the time it ends up in the same memory location.

    This shows what's happening very clearly (the output is likely to be different in other implementations of Python):

    class A:
        def __init__(self): print("a")
        def __del__(self): print("b")
    
    # a a b b False
    print(A() is A())
    # a b a b True
    print(id(A()) == id(A()))