Inverse of id()?

Duncan Booth duncan.booth at invalid.invalid
Mon May 21 04:10:15 EDT 2007


"Ian Clark" <turbana at gmail.com> wrote:

> Now I tried this in the shell and got different id's for a and b, but
> when I typed it into a file and ran from there the id's where always
> the same. Must have something to do with other programs allocating
> space faster than I can type everything out (I do have a few processes
> going). Interesting.
> 

No, what other processes are doing isn't going to affect the memory 
allocation within your Python process. More likely the interactive 
interpreter is allocating or releasing other objects when it compiles 
each line of input which stops you seeing the duplicated id. You can get 
it to reuse the id by making sure you force everything to be compiled in 
one go:

>>> class A: pass

>>> class B: pass

>>> a = A();print id(a);del a;b = B();print id(b)
12948384
12948384
>>> if 1:
	a = A()
	print id(a)
	del a
	b = B()
	print id(b)

	
12948464
12948464
>>> 

Gabriel's point however is not that this particular sequence will always 
result in duplicate ids (it is just an artifact of the implementation 
and could change), but that ids in general are re-used so any mapping 
from id->object is ambiguous unless you can be certain that the object 
whose id you took is still alive. 

There are two common ways to do the reverse mapping: either store the 
ids and objects  in a dict thereby forcing the objects to continue to 
exist, or store them in a weakref.WeakValueDictionary and be very 
careful not to access an expired (and possibly reused) id.

For a completely safe technique which works with any weakly 
referenceable object just ignore Python's id function and write your own 
which never reuses an id. Then you can safely map from your own id 
values back to the object if it still exists or get an exception if it 
doesn't:

>>> lastid = 0
>>> idmap = weakref.WeakValueDictionary()
>>> def myid(o):
	global lastid
	lastid += 1
	idmap[lastid] = o
	return lastid

>>> def getfrommyid(id):
	return idmap[id]

>>> a = A()
>>> print myid(a)
1
>>> del a
>>> b = B()
>>> print myid(b)
2
>>> print getfrommyid(2)
<__main__.B instance at 0x00CD43F0>
>>> print getfrommyid(1)

Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    print getfrommyid(1)
  File "<pyshell#25>", line 2, in getfrommyid
    return idmap[id]
  File "C:\Python25\Lib\weakref.py", line 54, in __getitem__
    o = self.data[key]()
KeyError: 1
>>> 

Unfortunately that won't help with the common builtin objects as they 
aren't weakly referenceable.





More information about the Python-list mailing list