And now for something completely Pythonic...

Finding objects' names

written by Georg, on Saturday, May 30, 2009 11:34.

Every now and then, Python newbies get into a situation where they think they need to know the “name” of an object, i.e. the name it is bound to. The canonical answer is that there is no such thing as a one-on-one mapping of objects and names; an object doesn’t need a name to be alive, only a reference to it, and a name can refer to many objects, depending which namespace you look at.

Still, Python’s introspection capabilities are powerful enough that it is possible to find out what names an object is bound to, which this snippet shows:

import gc, sys

def find_names(obj):
    frame = sys._getframe()
    for frame in iter(lambda: frame.f_back, None):
        frame.f_locals
    result = []
    for referrer in gc.get_referrers(obj):
        if isinstance(referrer, dict):
            for k, v in referrer.iteritems():
                if v is obj:
                    result.append(k)
    return result

foo = []

def demo():
    bar = foo
    print find_names(bar)

demo()
This prints [’foo’, ‘bar’].

The second part of the find_names function is straightforward once you know about the gc module; Python’s GC implementation makes it possible to query for all objects that refer (own a reference to) another object. This can be used to find all namespaces (which are just Python dictionaries) that reference our given object.

The first part is trickier: if you leave out the first three lines of the function, you will only get [’foo’] as the script’s output. It seems that there is no dictionary with “bar” referring to our object. What happens there?

Well, since the names of all locals are known at compile-time, Python “optimizes” function locals, putting them into an array instead of a dictionary, which speeds up access tremendously. But there is a way to get at the locals in a dictionary, namely the locals() function. There must be some way to get Python to create it for us! This is best done accessing the frame object’s f_locals attribute which creates and caches this dictionary, and that can be used to create dict references to all locals if the whole chain of currently executed frames is traversed, as the first for loop does.

Not that this function is useful for anything ;-)

Comments

  1. Ouch, I usually tell newbies to use a dictionary instead :-)

    - Paddy.

    —  Paddy3118 on Saturday, May 30, 2009 15:56 #

  2. As you should, premature optimization is the mother of all evil remember?

    —  rgz on Saturday, May 30, 2009 19:00 #

  3. What if the name is bound in a suspended generator?

    Getting-carried-away'ly
    Benjamin

    —  Benjamin on Tuesday, June 2, 2009 1:54 #

  4. you are aweful,

    bitten by the snake

    —  abki on Monday, June 22, 2009 1:51 #

  5. Names are always an issue, do you know why they named pickle the package to serialize the data?Cause they where eating pickles while they where doing it

    —  Mariana Soffer on Monday, June 22, 2009 4:10 #

  6. @Mariana Soffer:
    Don't feed the troll, plz... everybody know that pickle is a fool letter word.

    —  abki on Monday, June 22, 2009 5:20 #

  7. Nice. I’ve been trying to figure out if this is doable for some time. All the forums say no\don’t try. Not that I have a use for it either, but I like the mystery solved.

    —  Eric Pavey on Friday, January 8, 2010 19:02 #

Commenting is no longer possible.