Thus, basically every function has three things that can be considered function names:
Source code block name
It is stored in f.__code__.co_name (where f is the function object). If you create a function def orig_name , orig_name is the name. For lambas, this is <lambda> .
This attribute is read-only and cannot be changed. So the only way to create a function with a custom name at runtime that I know of is exec :
exec("""def {name}(): print '{name}' """.format(name='any')) in globals() any()
(There is also a lower-level way to do this , as mentioned in the commentary on the question.)
The inevitability of co_name really makes sense: with this, you can be sure that the name that you see in the debugger (or just a stack trace) is exactly the same as what you see in the source code (along with the file name and the string number).
The __name__ attribute of a function object
It also has the alias func_name .
You can change it ( orig_name.__name__ = 'updated name' ), and you certainly do it daily: @functools.wraps copies __name__ of the decorated function to a new one.
__name__ used by tools like pydoc , so you need @functools.wraps : so you don't see the technical details of each decorator in your documentation. Take a look at an example:
from functools import wraps def decorator1(f): def decorated(*args, **kwargs): print 'start1' f(*args, **kwargs) return decorated def decorator2(f): @wraps(f) def decorated(*args, **kwargs): print 'start2' f(*args, **kwargs) return decorated @decorator1 def test1(): print 'test1' @decorator2 def test2(): print 'test2'
Here is the pydoc output:
FUNCTIONS decorator1(f) decorator2(f) test1 = decorated(*args, **kwargs) test2(*args, **kwargs)
With wraps , there is no decorated sign in the documentation.
Link Name
Another thing that can be called the name of a function (although it is unlikely to exist) is the name of the variable or attribute that stores the link to this function.
If you create a function with def name , the name attribute will be added to the current scope. In the case of lambda you should assign the result to some variable: name = lambda: None .
Obviously, you can create multiple links to the same function, and all these links can have different names.
The only way to relate all three things to each other is with the def foo operator, which creates a function object with __name__ and __code__.co_name equal to foo and assigns the current volume to its foo attribute. But they are in no way connected and may differ from each other:
import traceback def make_function(): def orig_name(): """Docstring here """ traceback.print_stack() return orig_name globals()['name_in_module'] = make_function() name_in_module.__name__ = 'updated name' name_in_module()
Output:
File "my.py", line 13, in <module> name_in_module() File "my.py", line 7, in orig_name traceback.print_stack()
Pydoc:
FUNCTIONS make_function() name_in_module = updated name() Docstring here
I thank other people for comments and answers, they helped me organize my thoughts and knowledge.