views:

357

answers:

8

Is there any way to get the name of an object in Python? For instance:

my_list = [x, y, z] # x, y, z have been previously defined

for bla in my_list:
    print "handling object ", name(bla) # <--- what would go instead of `name`?
    # do something to bla

Edit: Some context:

What I'm actually doing is creating a list of functions that I can specify by the command line.

I have:

def fun1:
    pass
def fun2
    pass
def fun3:
    pass

fun_dict = {'fun1': fun1,
            'fun2': fun2,
            'fun3': fun3}

I get the name of the function from the commandline and I want to call the relevant function:

func_name = parse_commandline()

fun_dict[func_name]()

And the reason I want to have the name of the function is because I want to create fun_dict without writing the names of the functions twice, since that seems like a good way to create bugs. What I want to do is:

fun_list = [fun1, fun2, fun3] # and I'll add more as the need arises

fun_dict = {}
[fun_dict[name(t) = t for t in fun_list] # <-- this is where I need the name function

This way I only need to write the function names once.

+4  A: 

Objects do not necessarily have names in python, so you can't get the name. It's not unusual for objects to have a __name__ attribute in those cases that they do have a name, but this is not a part of standard python, and most built in types do not have one.

When you create a variable, like the x, y, z above then those names just act as "pointers" or "references" to the objects. The objects itself do not know what names you are using for it, and you can not easily (if at all) get the names of all references to an object.

Update: However, functions do have a __name__ (unless they are lambdas) so, in this case you can do:

dict([(t.__name__, t) for t in fun_list])
Lennart Regebro
+4  A: 

That's not really possible, as there could be multiple variables that have the same value, or a value might have no variable, or a value might have the same value as a variable only by chance.

If you really want to do that, you can use

def variable_for_value(value):
    for n,v in globals().keys():
        if v == value:
            return n
    return None

However, it would be better if you would iterate over names in the first place:

my_list = ["x", "y", "z"] # x, y, z have been previously defined

for name in my_list:
    print "handling variable ", name
    bla = globals()[name]
    # do something to bla
Martin v. Löwis
+1: When you evaluate `[a,b,c]` you have a list of objects, the variables themselves are irrelevant to the resulting list that's created.
S.Lott
Is this also true if the variables are objects, and not plain vanilla variables?
Nathan Fellman
@Nathan: Everything is objects in Python.
Lennart Regebro
A: 

Variable names can be found in the globals() and locals() dicts. But they won't give you what you're looking for above. "bla" will contain the value of each item of my_list, not the variable.

Todd
+1  A: 

Note that while, as noted, objects in general do not and cannot know what variables are bound to them, functions defined with def do have names in the __name__ attribute (the name used in def). Also if the functions are defined in the same module (as in your example) then globals() will contain a superset of the dictionary you want.

def fun1:
  pass
def fun2:
  pass
def fun3:
  pass

fun_dict = {}
for f in [fun1, fun2, fun3]:
  fun_dict[f.__name__] = f
Kathy Van Stone
A: 

Generally when you are wanting to do something like this, you create a class to hold all of these functions and name them with some clear prefix cmd_ or the like. You then take the string from the command, and try to get that attribute from the class with the cmd_ prefixed to it. Now you only need to add a new function/method to the class, and it's available to your callers. And you can use the doc strings for automatically creating the help text.

As described in other answers, you may be able to do the same approach with globals() and regular functions in your module to more closely match what you asked for.

Something like this:

class Tasks:
    def cmd_doit(self):
        # do it here

func_name = parse_commandline()
try:
    func = getattr('cmd_' + func_name, Tasks())
except AttributeError:
    # bad command: exit or whatever
func()
retracile
A: 

Here's another way to think about it. Suppose there were a name() function that returned the name of its argument. Given the following code:

def f(a):
    return a

b = "x"
c = b
d = f(c)

e = [f(b), f(c), f(d)]

What should name(e[2]) return, and why?

Robert Rossney
+1  A: 

And the reason I want to have the name of the function is because I want to create fun_dict without writing the names of the functions twice, since that seems like a good way to create bugs.

For this purpose you have a wonderful getattr function, that allows you to get an object by known name. So you could do for example:

funcs.py:

def func1(): pass
def func2(): pass

main.py:

import funcs
option = command_line_option()
getattr(funcs, option)()
SilentGhost
Cleaner answer than mine :)
retracile
Using this I could end up calling *any* function, right? Isn't this somewhat unsafe?
Nathan Fellman
you could only call function that are within namespace of `funcs`. of course you should filter all user input, it's rule correct even in Python, but you can make `funcs` to be a clean interface module, which you probably should do anyway. `getattr` also allows for a default fallback values.
SilentGhost
A: 

Use a reverse dict.

fun_dict = {'fun1': fun1,
            'fun2': fun2,
            'fun3': fun3}

r_dict = dict(zip(fun_dict.values(), fun_dict.keys()))

The reverse dict will map each function reference to the exact name you gave it in fun_dict, which may or may not be the name you used when you defined the function. And, this technique generalizes to other objects, including integers.

For extra fun and insanity, you can store the forward and reverse values in the same dict. I wouldn't do that if you were mapping strings to strings, but if you are doing something like function references and strings, it's not too crazy.

steveha
Ack, I just re-read your question and I understand it now. You want to get the names of the functions to build fun_dict in the first place, for which this technique is useless. I'll leave this here because you might have a use for the reverse dict later, perhaps in writing error messages or something.
steveha