从函数内部确定函数名

749 投票
27 回答
478080 浏览
提问于 2025-04-16 12:13

有没有办法在一个函数内部获取这个函数的名字呢?

def foo():
    print("my name is", __myname__)  # <== how do I calculate this at runtime?

在上面的例子中,函数 foo 的内部可以以某种方式获取到它自己的名字 "foo",而不需要直接写死这个名字。输出结果将会是:

>>> foo()
my name is foo

27 个回答

282

有几种方法可以得到相同的结果:

import sys
import inspect

def what_is_my_name():
    print(inspect.stack()[0][0].f_code.co_name)
    print(inspect.stack()[0][3])
    print(inspect.currentframe().f_code.co_name)
    print(sys._getframe().f_code.co_name)

请注意,inspect.stack 这个调用的速度比其他方法慢上千倍:

$ python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][0].f_code.co_name'
1000 loops, best of 3: 499 usec per loop
$ python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][3]'
1000 loops, best of 3: 497 usec per loop
$ python -m timeit -s 'import inspect, sys' 'inspect.currentframe().f_code.co_name'
10000000 loops, best of 3: 0.1 usec per loop
$ python -m timeit -s 'import inspect, sys' 'sys._getframe().f_code.co_name'
10000000 loops, best of 3: 0.135 usec per loop

更新于2021年8月(原帖是为Python2.7写的)

Python 3.9.1 (default, Dec 11 2020, 14:32:07)
[GCC 7.3.0] :: Anaconda, Inc. on linux

python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][0].f_code.co_name'
500 loops, best of 5: 390 usec per loop
python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][3]'
500 loops, best of 5: 398 usec per loop
python -m timeit -s 'import inspect, sys' 'inspect.currentframe().f_code.co_name'
2000000 loops, best of 5: 176 nsec per loop
python -m timeit -s 'import inspect, sys' 'sys._getframe().f_code.co_name'
5000000 loops, best of 5: 62.8 nsec per loop
589
import inspect

def foo():
   print(inspect.stack()[0][3])
   print(inspect.stack()[1][3])  # will give the caller of foos name, if something called foo

foo()

输出结果:

foo
<module_caller_of_foo>
290

如果你不想自己去处理栈的话,可以根据情况使用 "bar" 或者 bar.__name__

在Python中,函数内部没有办法直接访问到这个函数本身或者它的名字。曾经有个提议想在Python 3.0中加入一个神奇的 __function__,但最后被拒绝了。你可以查看这个提议的详细信息,链接在这里:PEP 3130 – 访问当前模块/类/函数

拒绝的通知内容是:

这个提议被拒绝了。因为不清楚应该如何实现,也不明确在一些特殊情况下应该是什么样的语义,而且没有提供足够重要的使用案例,大家的反应也不算热烈。

撰写回答