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

假设我有一个模块foo和一个功能栏。当执行foo.bar()时,是否有一种方法让bar知道bar的名字?或者更好的是,foo。酒吧的名字吗?

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

当前回答

这是一个经得起考验的方法。

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

_hidden和潜在弃用的方法 在堆栈中建立索引(可以在未来的python中重新排序)

所以我认为这对未来的python版本(在2.7.3和3.3.2测试)很有帮助:

from __future__ import print_function
import inspect

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

更新:在3.7.10,3.8.10和3.9.5测试

其他回答

我建议不要依赖于堆栈元素。如果有人在不同的上下文中使用你的代码(例如python解释器),你的堆栈将改变并破坏你的索引([0][3])。

我建议你这样做:

class MyClass:

    def __init__(self):
        self.function_name = None

    def _Handler(self, **kwargs):
        print('Calling function {} with parameters {}'.format(self.function_name, kwargs))
        self.function_name = None

    def __getattr__(self, attr):
        self.function_name = attr
        return self._Handler


mc = MyClass()
mc.test(FirstParam='my', SecondParam='test')
mc.foobar(OtherParam='foobar')
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())

测试:

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

输出:

test_class_func_name
test_func_name

我把这个实用工具放在附近:

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

用法:

myself()

使用__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__形参,包括它属于哪个类(参见限定名称)。

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 >