如何在Python中获取函数名
在Python编程中,有时候我们需要获取当前正在执行的函数的名称,例如统计一个模块中各个函数的调用次数,或者在程序的日志中打印出当前函数的名称。本文将介绍在Python中如何获取函数的名称。
阅读更多:Python 教程
使用name属性获取函数名
在Python中,每个函数都有一个特殊的属性__name__
,它返回函数的名称。我们可以在函数内部访问这个属性来获取函数的名称。例如:
def foo():
print(f"当前正在执行的函数名是:{foo.__name__}")
foo()
运行结果如下:
当前正在执行的函数名是:foo
在上面的例子中,我们定义了一个名为foo
的函数,然后在函数内部通过foo.__name__
获取了函数的名称。
虽然我们可以直接访问__name__
属性来获取函数的名称,但这种方法存在一些问题。如果我们想要获取其他函数的名称,就需要重复同样的代码。此外,如果我们更改了函数的名称,我们需要在访问__name__
属性的地方进行更新。
为了解决这些问题,我们可以使用装饰器来包装函数和添加一个新的函数来获取函数名称。这也是Python中最常见的一种获取函数名称的方法。
使用装饰器获取函数名
装饰器是一个函数,它接受另一个函数作为参数并返回一个新函数。我们可以使用装饰器来包装函数,并在每次函数调用时记录函数的信息,例如函数名称和调用次数。下面是一个使用装饰器获取函数名称的示例代码:
import functools
def count_calls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
wrapper.__count += 1
print(f"函数 {func.__name__} 被调用了 {wrapper.__count} 次")
return func(*args, **kwargs)
wrapper.__count = 0
return wrapper
@count_calls
def foo():
print("foo is called")
@count_calls
def bar():
print("bar is called")
foo()
foo()
bar()
foo()
bar()
运行结果如下:
foo is called
函数 foo 被调用了 1 次
foo is called
函数 foo 被调用了 2 次
bar is called
函数 bar 被调用了 1 次
foo is called
函数 foo 被调用了 3 次
bar is called
函数 bar 被调用了 2 次
在上面的例子中,我们定义了一个装饰器count_calls
,它包装了函数并记录了函数的名称和调用次数。装饰器内部使用了Python标准库中的functools.wraps
来保留原函数的元信息,例如函数名称和文档字符串。
我们使用@count_calls
装饰foo
和bar
函数,这意味着每次调用这些函数时都会调用我们的装饰器,并输出当前调用的函数名称和此函数被调用的次数。
使用inspect模块获取函数名
Python标准库中的inspect
模块也提供了一些方法来获取函数的名称和信息。下面是一些使用inspect
模块获取函数名称的示例代码:
import inspect
def foo():
print(f"当前正在执行的函数名是:{inspect.stack()[0][3]}")
foo()
运行结果如下:
当前正在执行的函数名是:foo
在上面的例子中,我们使用inspect.stack()
方法获取当前堆栈,并查找包含当前函数的堆栈帧。inspect.stack()
方法返回一个元组列表,其中每个元组表示一个堆栈帧。
我们使用inspect.stack()[0]
获取堆栈的第一个元组,它表示当前堆栈帧,然后使用[3]
获取包含当前函数名称的元素,最后输出函数名称。
使用inspect
模块可以获取更多函数信息,例如函数参数、函数默认值等等。下面是另一个使用inspect
模块获取函数名称和参数的示例代码:
import inspect
def foo(a, b=0, *args, **kwargs):
frame = inspect.currentframe()
args_info = inspect.getargvalues(frame)
print(f"当前正在执行的函数名是:{args_info.function}, 参数列表是:{args_info.args}")
foo(1, 2, 3, 4, c=5, d=6)
运行结果如下:
当前正在执行的函数名是:foo, 参数列表是:['a', 'b', 'args', 'kwargs']
在上面的例子中,我们定义了一个包含不同参数类型的函数foo
。我们使用inspect.currentframe()
方法获取当前堆栈帧,并使用inspect.getargvalues()
方法获取当前函数的参数列表。我们在输出中包含函数的名称和参数列表。
结论
在Python中,我们可以使用多种方法来获取正在执行的函数的名称。使用__name__
属性可以直接访问函数名称,使用装饰器可以记录函数调用信息,并使用inspect
模块可以获取更多函数信息。在实际编程中,我们可以根据需求和习惯选择最合适的方式来获取函数名称。