Reputation: 653
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
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
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
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
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