从函数内部确定函数名
有没有办法在一个函数内部获取这个函数的名字呢?
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 – 访问当前模块/类/函数。
拒绝的通知内容是:
这个提议被拒绝了。因为不清楚应该如何实现,也不明确在一些特殊情况下应该是什么样的语义,而且没有提供足够重要的使用案例,大家的反应也不算热烈。