Reputation: 2206
Background
I came to know recently that this is because the garbage collection would clear the contents of the location anytime, so relying on it would be a bad idea. There could be some other reason too, but I don't know.
I also came to know we could access an object given its location using C, because the in CPython address=id of the object. (I should thank the IRC guys for this.). But I haven't tried it.
I am talking about this address (id):
address = id(object_name)
or may be this one (if that helps):
hex_address = hex(id(object))
Anyway, I still think it would have been better if they gave some method that could do that for me.
I wouldn't want to use such a method in practice, but it bothers me that we have an object and something that would give its address, but nothing that does the vice-versa.
Question
Upvotes: 0
Views: 356
Reputation: 60137
As I wrote elsewhere:
id
is only defined as a number unique to the element among currently existing elements. Some Python implementations (in fact, all main ones but CPython) do not return the memory address.
%~> pypy
Python 2.7.3 (480845e6b1dd219d0944e30f62b01da378437c6c, Aug 08 2013, 17:02:19)
[PyPy 2.1.0 with GCC 4.8.1 20130725 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``arguably, everything is a niche''
>>>> a = 1
>>>> b = 2
>>>> c = 3
>>>> id(a)
9L
>>>> id(b)
17L
>>>> id(c)
25L
So you have to guarantee that it is the memory address. Furthermore, because of this Python provides no id → object
mapping, especially as the object that an id
maps to can be changed if the original is deleted.
You have to ask why you're holding the id
. If it's for space reasons, bear in mind that containers actually hold references to items, so [a, a, a, a, a]
actually takes less space than [id(a), id(a), id(a), id(a), id(a)]; a
.
You can consider also making a dict
of {id: val}
for all the relevant items and storing that. This will keep val
alive, so you can use weakref
s to allow the val
s to be garbage collected. Remember, use weakref
if you want a weakref
.
So basically it's because there's no reliable solution that's platform-independant.
it bothers me that we have an object and something that would give its address
Then just remember that we do not. CPython only optimises id
under the (correct) assumption that the address is unique. You should never treat is as an address because it's not defined to be.
Why was this decision made?
Because if we were to access things from their id
we'd be able to do all sorts of stupid stuff like accessing uninitialised stuff. It also prevents interpreters from optimising things by moving addresses around (JIT compilers like PyPy could not exist as easily if items had to have memory addresses). Furthermore, there is no guarantee that the item is either alive or even the same item at any point.
When references take less space than an integer (which is a reference + an numeric object) there is no point just not using a reference(or a weakref
if preferred), which will always do the right thing.
Upvotes: 1
Reputation: 66805
The simplest answer would be: "because it is not needed, and it is easier to maintain the code without low level access to variables".
A bit more elaborate is that everything you could do with such pointer, you can also do with basic references in python, or weakreferences (if you want to refer to some object without forbidding its garbage collection).
regarding "hacking":
You can iterate through garbage collector and take out the object
import gc
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
You can use mxtools
mx.Tools.makeref(id_)
You can use ctypes
ctypes.cast(id_, ctypes.py_object).value
Upvotes: 8