获取定义了函数的框架对象

时间:2012-02-18 08:07:52

标签: python introspection

有没有办法以编程方式找到定义函数的框架?我正在寻找像这样的函数get_defining_frame的东西:

def foo():
    def bar():
        pass
    return bar

bar = foo()

get_defining_frame(foo) # should be the same as inspect.currentframe()
get_defining_frame(bar) # should be the frame created by the call to foo

谢谢!

3 个答案:

答案 0 :(得分:0)

每次调用函数时都会创建/删除帧。所以当你打电话时:

get_defining_frame(bar)

在您的示例代码中,创建bar的框架已经消失。

函数对象不会对它们所定义的帧进行引用。这是一件好事,因为它会使所有其他局部变量不被释放。

你为什么需要这个?

答案 1 :(得分:0)

你不能得到这种信息,除非你自己存储(也许是装饰者)。 看看bar.__code__bar.__closure__,也许他们会为您提供足够的信息。 __closure__不会存储创建bar时的整个上下文,只会存储bar引用的变量,以节省内存效率。

应该做的伎俩:

def save_frame(func):
    frame=inspect.currentframe().f_back
    func.__frame = frame
    return func

请记住,使用它会真正搞乱垃圾收集,存储整个堆栈帧意味着堆栈中任何地方都没有任何引用可以进行GC编辑(这就是为什么__closure__只捕获引用的内容)。

答案 2 :(得分:0)

这是我在另一个主题上发布的答案的摘录,但发现它非常适用于该问题。它会向上移动框架以定位定义功能或应该在其中定义功能的位置。

下面的代码旨在查找是否已在类,模块或__main__中定义了函数。在返回找到的内容之前,它已经找到了声明该函数的对象的本地字典。因此可以对其进行修改以返回本地语言字典或框架。

解决的问题是在将函数绑定到类之前,如何在类声明期间找到函数的作用域。因此o.__self__或其他属性尚未分配。这是装饰器实现的一部分。

这适用于Python 3,但不适用于2。

>>> def _find_scope(func):
...     try:
...         owner_qname = '.'.join(func.__qualname__.split('.')[:-1])
...         if len(owner_qname) == 0:
...             module = sys.modules['__main__']
...             if hasattr(module, func.__name__):
...                 return module.__dict__
...             else:
...                 return None
...         i = 0
...         while True:
...             f_locals = sys._getframe(i).f_locals
...             i += 1
...             if ('__qualname__' in f_locals and
...                 f_locals['__qualname__'] == owner_qname):
...                     if func.__name__ in f_locals:
...                         return f_locals
...                     else:
...                         return None
...     except ValueError:
...         return None