Determining names of instances

Nick Mathewson nickm at mit.edu
Mon Jan 15 23:39:47 EST 2001


On Mon, 15 Jan 2001 14:42:52 -0800, Daniel Klein <DanielK at jBASE.com> wrote:
>A question I hope has a simple answer. Take the following simple class and
>instance
>
>    class foobar:
>        pass
>
>    foo = foobar()
>
>The question is, is there a way for the object 'foo' to know that its name
>is 'foo'?
>
>Daniel Klein

The short answer has been provided by others: not really.

The long answer is: yes, but you wouldn't want to.

# varname.py
from types import *
import sys

# We need python 2
assert sys.version_info[0] >= 2

def varname(object,depth):
    try:
	raise ""
    except:
	frame = sys.exc_traceback.tb_frame.f_back

    seen={}
    refs = [lr[1:] for lr in _searchInDict(object, 
					   frame.f_locals, 
					   depth, 
					   seen, 
					   1) ]
    if frame.f_globals is not frame.f_locals:
	refs += [gr[1:] for gr in _searchInDict(object, 
						frame.f_globals, 
						depth, 
						seen, 
						1) ]
    return refs

def _search(obj, target, depth=1, seen=None):
    if seen is None:
	seen = {}

    #if seen.get(id(target)):
    #	return ()
    #seen[id(target)] = 1
	
    if obj is target:
	return [""]

    if depth <= 0:
	return []

    t = type(target)
    if t is ClassType:
	return _searchInDict(obj, target.__dict__, depth, seen, 1)
    elif t is DictType:
	return _searchInDict(obj, target, depth, seen, 0)
    elif t is InstanceType:
	x = _searchInDict(obj, target.__dict__, depth, seen, 1)
	return x+_searchInDict(obj,target.__class__.__dict__,depth,seen,1)
    elif t in (ListType, TupleType):
	return _searchInSeq(obj, target, depth, seen)
    elif t is ModuleType:
	return _searchInDict(obj, target.__dict__, depth, seen, 1) 

    return []

def _searchInDict(obj,dict,depth,seen,isAttr):
    lst = []
    for k,v in dict.items():
	if v is obj:
	    lst.append( (isAttr and "."+k) or "[%s]"%`k` )
	else:
	    for x in _search(obj,v,depth-1,seen):
		lst.append( (isAttr and ".%s%s" %(k,x)) or "[%s]%s" %(`k`,x) )

    return lst

def _searchInSeq(obj,seq,depth,seen):
    lst = []

    for i in range(len(seq)):
	if seq[i] is obj:
	    lst.append( "["+i+"]")
	elif depth:
	    for x in _search(obj,seq[i],depth-1,seen):
		lst.append("["+i+"]"+x)

    return lst

######
Use:


>>> from varname import varname

>>> x = "Hello world"
>>> varname(x, 1)
['x']
# Ok, that worked...

>>> p=y=t=h=o=n = x
>>> varname(x, 1)
['y', 't', 'p', 'n', 'o', 'h', 'x']
#... but what is the true name of 'x'?

>>> x = "Goodbye simplicity"
>>> varname(x, 6)
["sys.modules['__main__'].x", "sys.modules['sys'].modules['__main__'].x", 'x']
# ... and which of these is the name of 'x' now?

######

The moral is a corolary to Fredrik Lundh's cat analogy: Although your
neighbors (namespaces) can tell you the names they call the cat
(object), and although they can tell you what names that their friends
call the cat -- if you really want the cat (object) to have a name of its
own, you'll need to put a tag around its neck (set an attribute).

Too-much-time-on-my-hands-too-look-in-the-archive-ly y'rs,

-- 
Nick Mathewson     <ZnickZm at alum.mit.edu>    without the zees.



More information about the Python-list mailing list