Python代码获取当前函数到一个变量? [英] Python code to get current function into a variable?

查看:303
本文介绍了Python代码获取当前函数到一个变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获得包含Python中当前正在执行的函数的变量?我不想要这个函数的名字。我知道我可以使用 inspect.stack 来获取当前的函数名称。我想要实际的可调用对象。可以在不使用 inspect.stack 来检索函数的名称,然后使用 eval 名称来获得可调用对象?



编辑:我有理由这样做,但它甚至不是一个好的。我使用 plac 来解析命令行参数。通过执行 plac.call(main)来使用它,它从main的函数签名中生成一个ArgumentParser对象。在main里面,如果参数有问题,我想退出时会出现一条错误消息,其中包含来自ArgumentParser对象的帮助文本,这意味着我需要通过调用直接访问此对象。 plac.parser_from(主).print_help()。我们可以这样说: plac.parser_from(get_current_function())。print_help(),这样我就不依赖于名为main 。现在,我的get_current_function的实现将是:

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

但是这个实现依赖于这个函数有一个名字,我想这不是太繁重。我永远不会做 plac.call(lambda ...)



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

func_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如果getattr(func,func_code,None)为代码:
(func,func_globals,None)为globs:
funcs.append (func)
len(funcs)> 1:
返回无
返回funcs [0] if funcs else无

一些测试用例:

  def foo():
return giveupthefunc()

zed = lambda:giveupthefunc()

bar,foo = foo,None

print bar()
print zed()

我不确定这个的性能特征,但我认为它应该适用于您的用例。


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?

Edit: 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])

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 ...).

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.

解决方案

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 func_code attribute, we have found the function.

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.

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, "func_code", None) is code:
                if getattr(func, "func_globals", None) is globs:
                    funcs.append(func)
                    if len(funcs) > 1:
                        return None
    return funcs[0] if funcs else None

Some test cases:

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.

这篇关于Python代码获取当前函数到一个变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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