Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 704
spenthil Avatar asked Oct 06 '10 22:10

spenthil


People also ask

What does id () do in Python?

Python id() Function The id() function returns a unique id for the specified object. All objects in Python has its own unique id. The id is assigned to the object when it is created.

Why the id of float values are different when the same value is assigned to two different variables in Python?

In that case the float value containing variable may contain same data but reason behind is to mathematical rules. The only two value are consider after the point & remaining are value get neglected. so the we get two different addresses of the same data containing variables.

Why id is different in Python?

Example 1: Python id() Since both values are the same, the id is also the same. Note: Since ID is an assigned memory address, it can be different in different systems. So, the output on your system can be different.

Can two variables have the same id in Python?

Bookmark this question. Show activity on this post. according to this link Senderle answered that immutable object references have the same id and mutable objects like lists have different ids.


2 Answers

When you call id({}), Python creates a dict and passes it to the id function. The id function takes its id (its memory location), and throws away the dict. The dict is destroyed. When you do it twice in quick succession (without any other dicts being created in the mean time), the dict Python creates the second time happens to use the same block of memory as the first time. (CPython's memory allocator makes that a lot more likely than it sounds.) Since (in CPython) id uses the memory location as the object id, the id of the two objects is the same. This obviously doesn't happen if you assign the dict to a variable and then get its id(), because the dicts are alive at the same time, so their id has to be different.

Mutability does not directly come into play, but code objects caching tuples and strings do. In the same code object (function or class body or module body) the same literals (integers, strings and certain tuples) will be re-used. Mutable objects can never be re-used, they're always created at runtime.

In short, an object's id is only unique for the lifetime of the object. After the object is destroyed, or before it is created, something else can have the same id.

like image 60
Thomas Wouters Avatar answered Oct 22 '22 15:10

Thomas Wouters


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()))
like image 42
Glenn Maynard Avatar answered Oct 22 '22 14:10

Glenn Maynard