如何将当前函数转换为变量? [英] How to get current function into a variable?
问题描述
如何获取包含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 eval
ing 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屋!