从该函数中确定函数名称(不使用回溯)

在Python中,如果不使用traceback模块,是否有一种方法可以在该函数中确定函数的名称?

说我有一个function栏foo模块。 执行foo.bar() ,有没有方法让bar知道bar的名字? 或者更好, foo.bar的名字?

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

Python没有function来访问函数本身内的函数或其名称。 已经提出,但遭到拒绝。 如果你不想自己玩堆栈,你应该根据上下文使用"bar"bar.__name__

 import inspect def foo(): print inspect.stack()[0][3] 

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

 from __future__ import print_function 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 

你可以使用@Andreas Jung显示的方法来获得它被定义的名称,但是这可能不是该函数被调用的名称:

 import inspect def Foo(): print inspect.stack()[0][3] Foo2 = Foo >>> Foo() Foo >>> Foo2() Foo 

这个区别对你来说是否重要,我不能说。

 functionNameAsString = sys._getframe().f_code.co_name 

我想要一个非常相似的东西,因为我想把函数名放在我的代码中的许多地方的日志string中。 可能不是最好的方法来做到这一点,但这是一个获取当前函数名称的方法。

我发现了一个将写入函数名称的包装器

 from functools import wraps def tmp_wrap(func): @wraps(func) def tmp(*args, **kwargs): print func.__name__ return func(*args, **kwargs) return tmp @tmp_wrap def my_funky_name(): print "STUB" my_funky_name() 

这将打印

my_funky_name

存根

我附近有这个方便的工具:

 import inspect myself = lambda: inspect.stack()[1][3] 

用法:

 myself() 

这实际上是从其他问题的答案中得出的。

这是我的意见:

 import sys # for current func name, specify 0 or no argument. # for name of caller of current func, specify 1. # for name of caller of caller of current func, specify 2. etc. currentFuncName = lambda n=0: sys._getframe(n + 1).f_code.co_name def testFunction(): print "You are in function:", currentFuncName() print "This function's caller was:", currentFuncName(1) def invokeTest(): testFunction() invokeTest() # end of file 

这个版本比使用inspect.stack()更有优势,它应该快上千倍[参见Alex Melihoff关于使用sys._getframe()和使用inspect.stack()的文章和计时)。

print(inspect.stack()[0].function)似乎也工作(Python 3.5)。

我想inspect是这样做的最好方法。 例:

 import inspect def bar(): print "My name is", inspect.stack()[0][3] 
 import inspect def whoami(): return inspect.stack()[1][3] def whosdaddy(): return inspect.stack()[2][3] def foo(): print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy()) bar() def bar(): print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy()) foo() bar() 

在IDE中输出代码

你好,我是富,爸爸是

你好,我是酒吧,爸爸是富

你好,我是酒吧,爸爸是

 import sys def func_name(): """ :return: name of caller """ return sys._getframe(1).f_code.co_name class A(object): def __init__(self): pass def test_class_func_name(self): print(func_name()) def test_func_name(): print(func_name()) 

testing:

 a = A() a.test_class_func_name() test_func_name() 

输出:

 test_class_func_name test_func_name 

这是一个面向未来的方法。

将@ CamHart's和@Yuval的build议与@ RoshOxymoron的接受答案结合起来可以避免:

  • _hidden和可能被弃用的方法
  • 索引到堆栈中(可以在未来的python中重新sorting)

所以我认为这与未来的Python版本(在2.7.3和3.3.2testing)很好玩:

 from __future__ import print_function import inspect def bar(): print("my name is '{}'".format(inspect.currentframe().f_code.co_name)) 

你可以使用装饰器:

 def my_function(name=None): return name def get_function_name(function): return function(name=function.__name__) >>> get_function_name(my_function) 'my_function' 

我做了CamHart所说的:

 import sys def myFunctionsHere(): print(sys._getframe().f_code.co_name) myFunctionsHere() 

输出:

C:\ Python \ Python36 \ python.exe C:/Python/GetFunctionsNames/TestFunctionsNames.py myFunctionsHere

进程使用退出码0结束

我做我自己的方法用于多重inheritance情况下安全调用超级(我把所有的代码)

 def safe_super(_class, _inst): """safe super call""" try: return getattr(super(_class, _inst), _inst.__fname__) except: return (lambda *x,**kx: None) def with_name(function): def wrap(self, *args, **kwargs): self.__fname__ = function.__name__ return function(self, *args, **kwargs) return wrap 

样本用法:

 class A(object): def __init__(): super(A, self).__init__() @with_name def test(self): print 'called from A\n' safe_super(A, self)() class B(object): def __init__(): super(B, self).__init__() @with_name def test(self): print 'called from B\n' safe_super(B, self)() class C(A, B): def __init__(): super(C, self).__init__() @with_name def test(self): print 'called from C\n' safe_super(C, self)() 

testing它:

 a = C() a.test() 

输出:

 called from C called from A called from B