6

I am very confused with the python code below:

>>> class A(): pass  
...  
>>> id(A()) == id(A())  
True  
>>> id(A())  
19873304  
>>> id(A())  
19873304
>>> A() is A()
False
>>> a = A()
>>> b = A()
>>> id (a) == id (b)
False
>>> a is b
False
>>> id (a)
19873304
>>> id (b)
20333272
>>> def f():
...     print id(A())
...     print id(A())
...
>>> f()
20333312
20333312

I can tell myself clearly what python doing when creating objects.
Can anyone tell me more about what happend? Thanks!

nevesly
  • 300
  • 2
  • 4
  • 13

4 Answers4

5

Two different objects can be at the same location in memory, if one of them is freed before the other is created.

That is to say -- if you allocate an object, take its id, and then have no more reference to it, it can then be freed, so another object can get the same id.

By contrast, if you retain a reference to the first object, any subsequent object allocated will necessarily have a different id.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
5

When you say

print id(A()) == id(A())

you are creating an object of type A and passing it to id function. When the function returns there are no references to that object created for the parameter. So, the reference count becomes zero and it becomes ready for garbage collection.

When you do id(A()) in the same expression again, you are trying to create another object of the same type. Now, Python might try to reuse the same memory location which was used for the previous object created (if it is already garbage collected). Otherwise it will create it in a different location. So, id may or may not be the same.

If you take,

print A() is A()

We create an object of type A and we are trying to compare it against another object of type A. Now the first object is still referenced in this expression. So, it will not marked for garbage collection and so the references will be different always.

Suggestion: Never do anything like this in production code.

Quoting from the docs,

Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the is operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
0

A() creates a temporary variable and then clears it

so the next A() gets the same id (that was just garbage collected,although this behavior is probably not guaranteed))... thus when you print them they have the same id

id(A()) == id(A())

has to create two temporary variables each with a different id

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
0

Since id() is based on object pointer, it is only guaranteed to be unique if both objects are in memory. In some situations, the second instance of A probably reused the same spot in memory of the first (that had already been garbage-collected).

epx
  • 1,066
  • 9
  • 17