如何将当前函数转换为变量? [英] How to get current function into a variable?

查看:126
本文介绍了如何将当前函数转换为变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How can I get a variable that contains the currently executing function in Python? I don't want the function's name. I know I can use inspect.stack to get the current function name. I want the actual callable object. Can this be done without using inspect.stack to retrieve the function's name and then evaling the name to get the callable object?

我有这样做的理由,但它甚至不是一个很好的选择.我正在使用 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"的实现是:

I have a reason to do this, but it's not even a remotely good one. I'm using plac to parse command-line arguments. You use it by doing plac.call(main), which generates an ArgumentParser object from the function signature of "main". Inside "main", if there is a problem with the arguments, I want to exit with an error message that includes the help text from the ArgumentParser object, which means that I need to directly access this object by calling plac.parser_from(main).print_help(). It would be nice to be able to say instead: plac.parser_from(get_current_function()).print_help(), so that I am not relying on the function being named "main". Right now, my implementation of "get_current_function" would be:

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

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

But this implementation relies on the function having a name, which I suppose is not too onerous. I'm never going to do plac.call(lambda ...).

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

In the long run, it might be more useful to ask the author of plac to implement a print_help method to print the help text of the function that was most-recently called using plac, or something similar.

推荐答案

堆栈框架会告诉我们我们所在的代码对象.如果我们可以在__code__属性中找到引用该代码对象的函数对象,我们已经找到了功能.

The stack frame tells us what code object we're in. If we can find a function object that refers to that code object in its __code__ attribute, we have found the function.

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

Fortunately, we can ask the garbage collector which objects hold a reference to our code object, and sift through those, rather than having to traverse every active object in the Python world. There are typically only a handful of references to a code object.

现在,函数可以共享代码对象,并且在从函数 返回函数(即闭包)的情况下也可以执行.当使用给定代码对象的功能不止一个时,我们无法确定它是哪个功能,因此我们返回None.

Now, functions can share code objects, and do in the case where you return a function from a function, i.e. a closure. When there's more than one function using a given code object, we can't tell which function it is, so we return 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()

我不确定此功能的性能,但是我认为这对您的用例来说应该没问题.

I'm not sure about the performance characteristics of this, but i think it should be fine for your use case.

这篇关于如何将当前函数转换为变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆