Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repeatable id clashes on python objects [duplicate]

Tags:

python

I understand that the python builtin id() returns an ID that is unique for the lifetime of an object. Objects with non-overlapping lifetimes, I understand, can end up with the same ID. However, I am trying to understand this rather confusing behavior:

>>> id(matplotlib.image.BboxImage.set_cmap)
4424372944
>>> id(numpy.ma.core.MaskedArray.sum)
4424372944

And in fact across multiple interpreter instances, the behavior is repeatable:

Mac:~$ python2.7 -c "import matplotlib.image; import numpy; print id(matplotlib.image.BboxImage.set_cmap), id(numpy.ma.core.MaskedArray.sum)"
4343186208 4343186208
Mac:~$ python2.7 -c "import matplotlib.image; import numpy; print id(matplotlib.image.BboxImage.set_cmap), id(numpy.ma.core.MaskedArray.sum)"
4521153312 4521153312
Mac:~$ python2.7 -c "import matplotlib.image; import numpy; print id(matplotlib.image.BboxImage.set_cmap), id(numpy.ma.core.MaskedArray.sum)"
4358591264 4358591264
Mac:~$ python2.7 -c "import matplotlib.image; import numpy; print id(matplotlib.image.BboxImage.set_cmap), id(numpy.ma.core.MaskedArray.sum)"
4389970720 4389970720

It appears that matplotlib.image.BboxImage.set_cmap and numpy.ma.core.MaskedArray.sum always get the same ID as each other, even across different instatiations of the python interpreter.

Now I understand that this is consistent with the docs for id() since those two objects are created dynamically when accessed and so will indeed have non-overlapping lifetimes. But why would those two unrelated objects always wind up with the same ID?

(This question is different to Object methods of same class have same id? because here I'm asking why this is repeatable across multiple interpreter instances, rather than simply a spurious id clash on objects with non-overlapping lifetimes.)

like image 783
Alex Flint Avatar asked Sep 24 '15 20:09

Alex Flint


1 Answers

This will be true of any instance method, which is the type of both the objects you are testing. Each time you access the descriptor, a new instancemethod object is instantiated. Since you aren't saving a reference to the newly created method, it is eligible for garbage collection as soon as id returns, and it apparently is being collected before the next call to id, so the same memory location can be reused.

This behavior can be seen in another way:

>>> x = matplotlib.image.BboxImage.set_cmap
>>> y = matplotlib.image.BboxImage.set_cmap
>>> id(x) == id(y)
False

x and y are references to two distinct objects, since referencing set_cmap creates a new instancemethod object each time.

like image 65
chepner Avatar answered Sep 21 '22 11:09

chepner