Jared Martin
Jared Martin

Reputation: 653

How do I get a functions current name in python

A small bit of code will explain why I'm asking and why this is not a duplicate. (I hope)

>>> def foo():
...    return 1
... 
>>> bar=foo
>>> bar.__name__
'foo'

How do I get 'bar'?

I've tried inspect and frames, but everything I've found so far fails this test.

Upvotes: 2

Views: 438

Answers (4)

l04m33
l04m33

Reputation: 606

Well it's an interesting question, can a function know what name it's called by? As far as I know, this piece of information is not stored in the stack or anywhere else, so to fetch it, we'll have to go into higher dimensions, or go meta, to manipulate the info of the source itself.

The result may not be useful, but it's funny :)

Below is the clumsy code:

import inspect
import io
import re

def get_my_name(func_obj):
    caller_frame = inspect.currentframe().f_back.f_back
    caller_mod = inspect.getmodule(caller_frame)
    mod_src = inspect.getsource(caller_mod)
    call_lineno = caller_frame.f_lineno

    stream = io.StringIO(mod_src)
    for i in range(0, call_lineno):
        line = stream.readline()
    m = re.findall('[_a-zA-Z0-9]+(?=\()', line)
    m = [fname for fname in m if caller_frame.f_locals[fname] == func_obj]
    return m

def some_func(n):
    print(get_my_name(some_func))
    return n*n

def caller():
    f = some_func
    return f(2)

caller()

Upvotes: 0

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250961

bar is just a reference to an already created object(foo), doing bar=foo means you created another reference to the same object.

In [62]: def foo():pass

In [63]: bar=foo

In [64]: spam=bar     #another reference to foo function object

In [65]: spam.__name__,bar.__name__
Out[65]: ('foo', 'foo')

In [66]: spam is foo,bar is foo
Out[66]: (True, True)

In [67]: import sys

In [68]: sys.getrefcount(foo)  # no of variable pointing to that object

Out[68]: 4           #3+1, 1 added by default by getrefcount()

Upvotes: 2

monkut
monkut

Reputation: 43840

If you know foo then you can check globals() to see if other functions are assigned to that function, note that this will pick up all other references:

>>> function_reference_names  = [k for k, v in globals().iteritems() if hasattr(globals()[k], "func_name") and globals()[k].func_name == bar.__name__ and k != bar.__name__]
>>> function_reference_names
['bar']

But as others have pointed out, if you want to do this, your probably asking the wrong question.

Upvotes: 0

Ned Batchelder
Ned Batchelder

Reputation: 375584

After you assign bar = foo, you have two names that both refer to the exact same value. There's no way in Python to distinguish between them. Assignment in Python never copies data, it just makes a name refer to a value, and a function is a value like any other. There is only one function, and it has only one __name__.

Upvotes: 1

Related Questions