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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With