小编典典

如何将当前函数转换为变量?

python

如何获取包含Python中当前正在执行的函数的变量?我不需要函数的名称。我知道我可以inspect.stack用来获取当前的函数名称。我想要实际的可调用对象。是否可以不使用inspect.stack检索函数名称,然后eval输入名称以获取可调用对象而完成此操作?

编辑:
我有这样做的理由,但它甚至不是一个很好的选择。我正在使用plac解析命令行参数。您可以通过使用来使用它plac.call(main),它会根据“
main”的函数签名生成一个ArgumentParser对象。在“
main”内部,如果参数存在问题,我想退出并显示一条错误消息,其中包含ArgumentParser对象的帮助文本,这意味着我需要通过调用直接访问此对象plac.parser_from(main).print_help()。可以这样说::plac.parser_from(get_current_function()).print_help(),这样我就不必依赖被命名为“
main”的函数了。现在,我对“ get_current_function”的实现是:

import inspect    
def get_current_function():
    return eval(inspect.stack()[1][3])

但是此实现依赖于具有名称的功能,我想这个名称不太繁琐。我永远不会做plac.call(lambda ...)

从长远来看,让plac的作者实现print_help方法来打印最近使用plac或类似方法调用的函数的帮助文本可能会更有用。


阅读 233

收藏
2020-12-20

共1个答案

小编典典

堆栈框架告诉我们我们位于哪个代码对象中。如果我们可以找到在其__code__属性中引用该代码对象的功能对象,那么我们已经找到了该功能。

幸运的是,我们可以询问垃圾回收器,哪些对象持有对我们代码对象的引用,并对其进行筛选,而不必遍历Python世界中的每个活动对象。通常只有很少的对代码对象的引用。

现在,函数可以共享代码对象,并且在
函数(例如闭包)返回函数的情况下也可以执行。当使用给定的代码对象有多个函数时,我们无法确定它是哪个函数,因此我们返回None

import inspect, gc

def giveupthefunc():
    frame = inspect.currentframe(1)
    code  = frame.f_code
    globs = frame.f_globals
    functype = type(lambda: 0)
    funcs = []
    for func in gc.get_referrers(code):
        if type(func) is functype:
            if getattr(func, "__code__", None) is code:
                if getattr(func, "__globals__", None) is globs:
                    funcs.append(func)
                    if len(funcs) > 1:
                        return None
    return funcs[0] if funcs else None

一些测试用例:

def foo():
    return giveupthefunc()

zed = lambda: giveupthefunc()

bar, foo = foo, None

print bar()
print zed()

我不确定这个的性能特征,但是我认为这对您的用例来说应该没问题。

2020-12-20