从别名函数中确定函数名称

Determine function name from within an aliased function

如何确定函数是使用函数名还是通过该函数的别名调用的?

我可以通过以下操作检查函数以从函数体内获取其名称:

import inspect

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

foo() # prints 'foo'

来源:Determine function name from within that function (without using traceback)

但是,如果我为函数添加别名并尝试相同的操作,我会得到原始函数名称(不是别名)

bar = foo
bar() # prints 'foo'

我希望能够做到以下几点:

def foo():
    print(... some code goes here ...)

bar = foo

foo() # prints 'foo'
bar() # prints 'bar'

我有一个(有点老套的)解决方案,它依靠正则表达式从字符串中解析出函数名称。可能有更简洁的解决方案,但至少仅使用 inspect 这是我能找到的最好的解决方案。

import inspect
import re


function_from_call = re.compile("\w+(?=\(\))")


def foo():
    _, call_frame, *_ = inspect.stack()
    _, _, _, _, call, *_ = call_frame
    print(re.search(function_from_call, str(call)).group())

bar = foo
bar()  # prints bar
foo()  # prints foo

简短说明:首先,我正在获取导致调用此函数的调用的检查框架。然后,我从该帧中提取实际的调用字符串,并将正则表达式应用于该调用字符串,仅提供函数名称。

注意:在解释器 shell 中,inspect 的行为有所不同,我上面的代码会产生错误,因为我的正则表达式无法匹配实际的函数名称。 @user2357112 在对这个问题的评论中指出了一个额外的警告:调用直接绑定到名称并不明显,如

l = [foo]; l[0]()

当从脚本中 运行 时,我的解决方案将正确处理简单的重命名情况(如本问题中给出的那样),但我不提倡使用它,因为像上面那样的极端情况会导致混淆错误。

基于我对你的问题范围的有限了解,这个有效:

import inspect

def foo():
  print(inspect.stack()[1][4][0].strip())

foo()
bar = foo
bar()

结果:

foo()
bar()