49

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.

martineau
  • 112,593
  • 23
  • 157
  • 280
Nathan Fellman
  • 116,304
  • 97
  • 251
  • 314
  • What should that function return in this case? – Joachim Sauer Oct 08 '09 at 14:56
  • 1
    As usual, I will ask you to tell us what the problem is that you are trying to solve. – Lennart Regebro Oct 08 '09 at 15:04
  • http://meta.stackexchange.com/questions/18584/how-to-ask-a-smart-question-on-so/25128#25128 – Lennart Regebro Oct 08 '09 at 15:19
  • @Lennart, is this any better? – Nathan Fellman Oct 08 '09 at 15:31
  • Yes. Because *functions* do have a `__name__` attribute. – Lennart Regebro Oct 08 '09 at 16:00
  • St like `def getname(obj): try: name = obj.__name__ except AttributeError as e: name = re.match("^'(.*)'", str(e)).group(1) return name` (or linear lookup for "'" instead of `re` module usage) ? – lef Nov 07 '17 at 11:47
  • Almost ten years and no explanation what you were trying to do? Declare some global functions? (but why no function body? or why not wrap them in your own package and import it?) And what was this code trying to do: have Python parse a (Windows/Unix) command-line for these names, then call the corresponding Python (global) function? And I don't see why they absolutely had to be global. I think the intent of your question was more *"How does Python resolve function/method references?"* – smci May 07 '18 at 02:18

18 Answers18

54

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 object itself does not know what name you are using for it, and you can not easily (if at all) get the names of all references to that object.

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

dict([(t.__name__, t) for t in fun_list])
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
Lennart Regebro
  • 158,668
  • 41
  • 218
  • 248
  • Solution: get the list of object names from globals(), iterating over them and testing for equality on `id(obj) == id(xx)` – smci Apr 22 '13 at 06:02
  • 6
    @smci: That assumes the object is in globals(), which it often is not, and it will give false positives on integers and many strings, and of course ignores the fact that many objects don't have a name in any case at all. Also, you should use `is`. – Lennart Regebro Apr 22 '13 at 06:34
  • All user-declared objects do have a name, right? In my case I'm usually interested in things I declared. – smci Apr 22 '13 at 14:23
  • 1
    @smci: No, that is not correct. They might also have several names. – Lennart Regebro Apr 22 '13 at 17:15
  • 'a name' as in 'at least one name'. So yes. I know about aliasing and I'd looked it - it's not a problem. – smci Apr 23 '13 at 02:35
  • Lennart, stop misquoting me. a) I said that **user-declared variables** have (at least) one name. That's all we need for the snippet to work. If you can provide a counterexample of a **user-declared variable** without a name, please do. b) I don't see how a user-declared variable could have more than one name, unless you're referring to a deep-copy. So: please give an example supporting your comment about more than one name. Specifics, please. – smci Apr 23 '13 at 09:42
  • One example of a nameless object is a cached constant: `id(666)`. But this was not user-declared. – smci Apr 23 '13 at 10:18
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28727/discussion-between-lennart-regebro-and-smci) – Lennart Regebro Apr 23 '13 at 11:07
  • 1
    Lennart, in the case of `foo = [MyClass()]` we declared an object and chose not to store it. We could have captured it if we wanted. So, refining the OP's question to **user-declared objects whose reference could not have been captured**. Still waiting for your specific examples of a non-aliased non-deepcopy object with more than one name. Stop being abusive, btw. You're violating the TOS. – smci Apr 23 '13 at 13:09
  • 1
    Discussion has continues in chat. There is no abuse from my side, all you need to do is listen and ask, and you will learn. – Lennart Regebro Apr 23 '13 at 13:34
  • 3
    pedantic prig, yes. Abusive? probably should be nicer is all i'd say. – eric May 06 '18 at 13:00
14

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().items():
        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

 

Andrew McLeod
  • 340
  • 1
  • 3
  • 12
Martin v. Löwis
  • 120,633
  • 17
  • 193
  • 234
12

This one-liner works, for all types of objects, as long as they are in globals() dict, which they should be:

def name_of_global_obj(xx):
    return [objname for objname, oid in globals().items()
            if id(oid)==id(xx)][0]

or, equivalently:

def name_of_global_obj(xx):
    for objname, oid in globals().items():
        if oid is xx:
            return objname
Max Ghenis
  • 12,769
  • 13
  • 73
  • 119
smci
  • 29,564
  • 18
  • 109
  • 144
  • 1
    Note that you will probably want to `not objname.startwith('_')`. I was getting a lot of results like id_26 or \_\_loader\_\_ that were clearly erroneous. Of course if you are declaring names starting with underscores then you may want to filter out \__ instead. I posted an answer including this stuff. – Six May 03 '15 at 21:41
  • @Six: yes we could add an argument `exclude` defaulting to `^_' and apply it – smci Feb 22 '20 at 01:00
8

If you are looking to get the names of functions or lambdas or other function-like objects that are defined in the interpreter, you can use dill.source.getname from dill. It pretty much looks for the __name__ method, but in certain cases it knows other magic for how to find the name... or a name for the object. I don't want to get into an argument about finding the one true name for a python object, whatever that means.

>>> from dill.source import getname
>>> 
>>> def add(x,y):
...   return x+y
... 
>>> squared = lambda x:x**2
>>> 
>>> print getname(add)
'add'
>>> print getname(squared)
'squared'
>>> 
>>> class Foo(object):
...   def bar(self, x):
...     return x*x+x
... 
>>> f = Foo()
>>> 
>>> print getname(f.bar)
'bar'
>>> 
>>> woohoo = squared
>>> plus = add
>>> getname(woohoo)
'squared'
>>> getname(plus)
'add'
Mike McKerns
  • 30,724
  • 8
  • 111
  • 135
5

As others have mentioned, this is a really tricky question. Solutions to this are not "one size fits all", not even remotely. The difficulty (or ease) is really going to depend on your situation.

I have come to this problem on several occasions, but most recently while creating a debugging function. I wanted the function to take some unknown objects as arguments and print their declared names and contents. Getting the contents is easy of course, but the declared name is another story.

What follows is some of what I have come up with.

Return function name

Determining the name of a function is really easy as it has the __name__ attribute containing the function's declared name.

name_of_function = lambda x : x.__name__

def name_of_function(arg):
    try:
        return arg.__name__
    except AttributeError:
        pass`

Just as an example, if you create the function def test_function(): pass, then copy_function = test_function, then name_of_function(copy_function), it will return test_function.

Return first matching object name

  1. Check whether the object has a __name__ attribute and return it if so (declared functions only). Note that you may remove this test as the name will still be in globals().

  2. Compare the value of arg with the values of items in globals() and return the name of the first match. Note that I am filtering out names starting with '_'.

The result will consist of the name of the first matching object otherwise None.

def name_of_object(arg):
    # check __name__ attribute (functions)
    try:
        return arg.__name__
    except AttributeError:
        pass

    for name, value in globals().items():
        if value is arg and not name.startswith('_'):
            return name

Return all matching object names

  • Compare the value of arg with the values of items in globals() and store names in a list. Note that I am filtering out names starting with '_'.

The result will consist of a list (for multiple matches), a string (for a single match), otherwise None. Of course you should adjust this behavior as needed.

def names_of_object(arg):
    results = [n for n, v in globals().items() if v is arg and not n.startswith('_')]
    return results[0] if len(results) is 1 else results if results else None
Six
  • 4,562
  • 3
  • 27
  • 37
2

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
  • 91,640
  • 24
  • 140
  • 215
2

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
  • 71,436
  • 20
  • 89
  • 116
  • 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 Oct 08 '09 at 18:35
1

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
  • 24,585
  • 3
  • 31
  • 40
1

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
  • 287,765
  • 61
  • 300
  • 288
  • Using this I could end up calling *any* function, right? Isn't this somewhat unsafe? – Nathan Fellman Oct 08 '09 at 21:09
  • 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 Oct 08 '09 at 21:30
1

I know This is late answer.

  1. To get func name , you can use func.__name__
  2. To get the name of any python object that has no name or __name__ method. You can iterate over its module members.

Ex:.

# package.module1.py

obj = MyClass()



# package.module2.py
import importlib
def get_obj_name(obj):
   mod = Obj.__module__ # This is necessary to 
   module = module = importlib.import_module(mod)
   for name, o in module.__dict__.items():
      if o == obj:
         return name

Performance note: don't use it in large modules.

tabebqena
  • 1,030
  • 1
  • 11
  • 17
0

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
  • 5,679
  • 2
  • 19
  • 21
0

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
  • 11,640
  • 2
  • 34
  • 42
0

I ran into this page while wondering the same question.

As others have noted, it's simple enough to just grab the __name__ attribute from a function in order to determine the name of the function. It's marginally trickier with objects that don't have a sane way to determine __name__, i.e. base/primitive objects like basestring instances, ints, longs, etc.

Long story short, you could probably use the inspect module to make an educated guess about which one it is, but you would have to probably know what frame you're working in/traverse down the stack to find the right one. But I'd hate to imagine how much fun this would be trying to deal with eval/exec'ed code.

% python2 whats_my_name_again.py
needle => ''b''
['a', 'b']
[]
needle => '<function foo at 0x289d08ec>'
['c']
['foo']
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
needle => '<__main__.a_class instance at 0x289d3aac>'
['e', 'd']
[]
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
%

whats_my_name_again.py:

#!/usr/bin/env python

import inspect

class a_class:
    def __init__(self):
        pass

def foo():
    def bar():
        pass

    a = 'b'
    b = 'b'
    c = foo
    d = a_class()
    e = d
    f = bar

    #print('globals', inspect.stack()[0][0].f_globals)
    #print('locals', inspect.stack()[0][0].f_locals)

    assert(inspect.stack()[0][0].f_globals == globals())
    assert(inspect.stack()[0][0].f_locals == locals())

    in_a_haystack = lambda: value == needle and key != 'needle'

    for needle in (a, foo, bar, d, f, ):
        print("needle => '%r'" % (needle, ))
        print([key for key, value in locals().iteritems() if in_a_haystack()])
        print([key for key, value in globals().iteritems() if in_a_haystack()])


foo()
0

You define a class and add the Unicode private function insert the class like

class example:
  def __init__(self, name):
    self.name = name

  def __unicode__(self):
    return self.name

Of course you have to add extra variable self.name which is the name of the object.

k0pernikus
  • 50,568
  • 57
  • 198
  • 317
0

Here is my answer, I am also using globals().items()

    def get_name_of_obj(obj, except_word = ""):

        for name, item in globals().items():
            if item == obj and name != except_word:
                return name

I added except_word because I want to filter off some word used in for loop. If you didn't add it, the keyword in for loop may confuse this function, sometimes the keyword like "each_item" in the following case may show in the function's result, depends on what you have done to your loop.

eg.

    for each_item in [objA, objB, objC]:
        get_name_of_obj(obj, "each_item")

eg.

    >>> objA = [1, 2, 3]
    >>> objB = ('a', {'b':'thi is B'}, 'c')
    >>> for each_item in [objA, objB]:
    ...     get_name_of_obj(each_item)
    ...
    'objA'
    'objB'
    >>>
    >>>
    >>> for each_item in [objA, objB]:
    ...     get_name_of_obj(each_item)
    ...
    'objA'
    'objB'
    >>>
    >>>
    >>> objC = [{'a1':'a2'}]
    >>>
    >>> for item in [objA, objB, objC]:
    ...     get_name_of_obj(item)
    ...
    'objA'
    'item'  <<<<<<<<<< --------- this is no good
    'item'
    >>> for item in [objA, objB]:
    ...     get_name_of_obj(item)
    ...
    'objA'
    'item'     <<<<<<<<--------this is no good
    >>>
    >>> for item in [objA, objB, objC]:
    ...     get_name_of_obj(item, "item")
    ...
    'objA'
    'objB'  <<<<<<<<<<--------- now it's ok
    'objC'
    >>>

Hope this can help.

ZoomRui
  • 19
  • 1
  • 5
0

Python has names which are mapped to objects in a hashmap called a namespace. At any instant in time, a name always refers to exactly one object, but a single object can be referred to by any arbitrary number of names. Given a name, it is very efficient for the hashmap to look up the single object which that name refers to. However given an object, which as mentioned can be referred to by multiple names, there is no efficient way to look up the names which refer to it. What you have to do is iterate through all the names in the namespace and check each one individually and see if it maps to your given object. This can easily be done with a list comprehension:

[k for k,v in locals().items() if v is myobj]

This will evaluate to a list of strings containting the names of all local "variables" which are currently mapped to the object myobj.

>>> a = 1
>>> this_is_also_a = a
>>> this_is_a = a
>>> b = "ligma"
>>> c = [2,3, 534]
>>> [k for k,v in locals().items() if v is a]

['a', 'this_is_also_a', 'this_is_a']

Of course locals() can be substituted with any dict that you want to search for names that point to a given object. Obviously this search can be slow for very large namespaces because they must be traversed in their entirety.

RBF06
  • 1,585
  • 1
  • 17
  • 18
0

Based on what it looks like you're trying to do you could use this approach.

In your case, your functions would all live in the module foo. Then you could:

import foo

func_name = parse_commandline()
method_to_call = getattr(foo, func_name)
result = method_to_call()

Or more succinctly:

import foo

result = getattr(foo, parse_commandline())()
wonkybadonk
  • 412
  • 4
  • 14
0

Hi there is one way to get the variable name that stores an instance of a class is to use

locals()

function, it returns a dictionary that contains the variable name as a string and its value

Holloway
  • 1
  • 3
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31438869) – vinzee Apr 04 '22 at 08:47