从该函数中确定函数名称(不使用回溯)
在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