如何在Python中获得函数名作为字符串?

在Python中,如何在不调用函数的情况下以字符串的形式获得函数名?

1
2
3
4
def my_function():
    pass

print get_function_name_as_string(my_function) # my_function is not in quotes

应该输出"my_function"

Python中有这样的函数吗?如果没有,有关于如何在Python中实现get_function_name_as_string的想法吗?


1
my_function.__name__

使用__name__是首选的方法,因为它的应用是一致的。与func_name不同的是,它也适用于内置函数:

1
2
3
4
5
6
7
>>> import time
>>> time.time.func_name
Traceback (most recent call last):
  File"<stdin>", line 1, in ?
AttributeError: 'builtin_function_or_method' object has no attribute 'func_name'
>>> time.time.__name__
'time'

此外,双下划线向读者表明这是一个特殊的属性。另外,类和模块也有一个__name__属性,所以您只需要记住一个特殊的名称。


你也可以用

1
2
import sys
this_function_name = sys._getframe().f_code.co_name


1
my_function.func_name

函数还有其他有趣的属性。键入dir(func_name)来列出它们。func_name.func_code.co_code是编译后的函数,存储为字符串。

1
2
import dis
dis.dis(my_function)

将以几乎人类可读的格式显示代码。:)


这个函数将返回调用者的函数名。

1
2
3
def func_name():
    import traceback
    return traceback.extract_stack(None, 2)[0][2]

这就像阿尔伯特·冯普(Albert Vonpupp)用友好的包装给出的答案。


如果您也对类方法感兴趣,Python 3.3+除了__name__之外还有__qualname__

1
2
3
4
5
6
7
8
9
10
11
12
def my_function():
    pass

class MyClass(object):
    def method(self):
        pass

print(my_function.__name__)         # gives"my_function"
print(MyClass.method.__name__)      # gives"method"

print(my_function.__qualname__)     # gives"my_function"
print(MyClass.method.__qualname__)  # gives"MyClass.method"


我喜欢使用函数装饰器。我添加了一个类,它也乘以函数时间。假设gLog是一个标准的python日志记录器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class EnterExitLog():
    def __init__(self, funcName):
        self.funcName = funcName

    def __enter__(self):
        gLog.debug('Started: %s' % self.funcName)
        self.init_time = datetime.datetime.now()
        return self

    def __exit__(self, type, value, tb):
        gLog.debug('Finished: %s in: %s seconds' % (self.funcName, datetime.datetime.now() - self.init_time))

def func_timer_decorator(func):
    def func_wrapper(*args, **kwargs):
        with EnterExitLog(func.__name__):
            return func(*args, **kwargs)

    return func_wrapper

现在你要做的就是装饰它

1
2
@func_timer_decorator
def my_func():


_getframe()不能保证在所有Python实现中都可用(参见参考资料),您可以使用回溯模块来做同样的事情,例如。

1
2
3
4
5
6
import traceback
def who_am_i():
   stack = traceback.extract_stack()
   filename, codeline, funcName, text = stack[-2]

   return funcName

调用stack[-1]将返回当前流程的详细信息。


作为@Demyn答案的扩展,我创建了一些实用函数来打印当前函数的名称和参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import inspect
import logging
import traceback

def get_function_name():
    return traceback.extract_stack(None, 2)[0][2]

def get_function_parameters_and_values():
    frame = inspect.currentframe().f_back
    args, _, _, values = inspect.getargvalues(frame)
    return ([(i, values[i]) for i in args])

def my_func(a, b, c=None):
    logging.info('Running ' + get_function_name() + '(' + str(get_function_parameters_and_values()) +')')
    pass

logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
    '%(asctime)s [%(levelname)s] -> %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

my_func(1, 3) # 2016-03-25 17:16:06,927 [INFO] -> Running my_func([('a', 1), ('b', 3), ('c', None)])

你只需要得到函数名这里有一个简单的代码。假设你定义了这些函数

1
2
3
4
5
6
7
8
9
def function1():
    print"function1"

def function2():
    print"function2"

def function3():
    print"function3"
print function1.__name__

输出将是function1

现在假设你有一个列表中的这些函数

1
a = [function1 , function2 , funciton3]

获取函数的名称

1
2
for i in a:
    print i.__name__

输出将是

function1
function2
function3


1
2
3
4
import inspect

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