在Python中,如果不使用traceback模块,是否有一种方法可以从函数内部确定函数的名称?
假设我有一个模块foo和一个功能栏。当执行foo.bar()时,是否有一种方法让bar知道bar的名字?或者更好的是,foo。酒吧的名字吗?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
在Python中,如果不使用traceback模块,是否有一种方法可以从函数内部确定函数的名称?
假设我有一个模块foo和一个功能栏。当执行foo.bar()时,是否有一种方法让bar知道bar的名字?或者更好的是,foo。酒吧的名字吗?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
当前回答
从上面所有使用inspect库的答案来看,所有的都是这样写的:
import inspect
inspect.stack()[0][3]
但是,由于inspect.stack()的返回,[0]是一个NamedTuple,其形式为:
FrameInfo(frame=<frame at 0x103578810, file '<stdin>', line 1, code <module>>, filename='<stdin>', lineno=1, function='<module>', code_context=None, index=None)
可以简单地通过名称调用,即inspect.stack()[0].function
这里可以看到一个小的虚拟例子:
def test_train_UGRIZY_noZ(self, architecture, dataset, hyperrun, wloss):
log.warning(f"{inspect.stack()[0].function} -- Not Implemented Yet")
pass
当运行时打印:
WARNING - test_train_UGRIZY_noZ -- Not Implemented Yet
其他回答
从上面所有使用inspect库的答案来看,所有的都是这样写的:
import inspect
inspect.stack()[0][3]
但是,由于inspect.stack()的返回,[0]是一个NamedTuple,其形式为:
FrameInfo(frame=<frame at 0x103578810, file '<stdin>', line 1, code <module>>, filename='<stdin>', lineno=1, function='<module>', code_context=None, index=None)
可以简单地通过名称调用,即inspect.stack()[0].function
这里可以看到一个小的虚拟例子:
def test_train_UGRIZY_noZ(self, architecture, dataset, hyperrun, wloss):
log.warning(f"{inspect.stack()[0].function} -- Not Implemented Yet")
pass
当运行时打印:
WARNING - test_train_UGRIZY_noZ -- Not Implemented Yet
我用自己的方法在多重继承场景中安全地调用super(我把所有代码都放在这里)
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)()
测试:
a = C()
a.test()
输出:
called from C
called from A
called from B
在每个@with_name修饰的方法中,您可以访问self。__fname__作为当前函数名。
import inspect
def method_name():
return inspect.stack()[1][3]
def method_name_caller():
return inspect.stack()[2][3]
def asdf():
print(method_name_caller())
print(method_name())
def asdf2():
print(method_name_caller())
print(method_name())
asdf()
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()
输出:
喷火 < module_caller_of_foo >
使用__name__属性:
# foo.py
def bar():
print(f"my name is {bar.__name__}")
你可以使用__name__属性轻松地从函数内部访问函数名。
>>> def bar():
... print(f"my name is {bar.__name__}")
...
>>> bar()
my name is bar
我自己也遇到过这个问题好几次,一直在寻找解决方法。正确答案包含在Python文档中(参见可调用类型部分)。
每个函数都有返回其名称的__name__形参,甚至还有返回其全名的__qualname__形参,包括它属于哪个类(参见限定名称)。