在 python 中,可以询问内部函数的父函数吗?

In python, can an inner function be interrogated about its parent function?

提问人:Azmy Rajab 提问时间:8/3/2023 更新时间:8/3/2023 访问量:33

问:

假设我们有一个函数,用 my_module.py 定义:

def make_function(scalar: float) -> Callable[[float], float]:
    
    def increment(x: float) -> float:
        return x + scalar
    
    return increment

在运行时,我可以访问实时的内部函数对象(我知道所有相关代码都是在my_module.py中定义的)。

>> make_function(2)
<function my_module.make_function.<locals>.increment(x: float) -> float>

问:有没有一种优雅的方法可以从活动对象中获取有关其父函数的信息?我特别感兴趣的是动态生成格式的字符串。我正在寻找一种解决方案,该解决方案也适用于任意数量的嵌套级别(即 )。"my_module.make_function.increment""my_module.outer_func_1.outer_func_2.inner_func"

请注意,根据我之前的代码示例,我的问题的答案似乎(几乎)嵌入在函数对象中。但不确定它背后的内部结构以及如何访问它们。__repr__

我试过了什么?

  • Inspect module:但仅返回模块路径inspect.getmodule(func).__name__
  • func.__code__.co_*,但找不到指向父函数的方法
  • 玩 ,但这似乎比需要的要复杂func.__globals__

理想情况下,我希望避免装饰/修改定义的功能,而只能通过检查对象本身来得出答案。非常感谢有关如何进行的任何帮助!

Python 命名空间

评论

0赞 Andrej Kesely 8/3/2023
为什么不呢?f = make_function(2); f.__repr__().replace("<locals>.", "")
0赞 Azmy Rajab 8/3/2023
你好!理想情况下,我希望看到/理解所使用的代码,以确保所需的行为是稳定的/没有会导致字符串显示不同的令人讨厌的极端情况。此外,如果有一个底层公共方法可以执行相同的操作 - 请稍微倾向于直接调用它。但是,除非这些是访问路径的最佳方式,那么是的,我会按照您的建议去做__repr__
1赞 juanpa.arrivillaga 8/3/2023
@AzmyRajab我会使用更“稳定”的方式。 可能不会改变,但只是为了安全起见......f.__qualname____repr__
1赞 Andrej Kesely 8/3/2023
@juanpa.arrivillaga 是的,我本来想说同样:) 是要走的路。显然,此属性是在编译时设置的,并且始终为内部函数设置。github.com/python/cpython/blob/......f.__qualname__<locals>
1赞 Azmy Rajab 8/3/2023
很酷 - 我只是尝试了几种情况(例如多级嵌套),它似乎确实表现得一致/符合预期谢谢你们俩的帮助!__qualname__

答:

2赞 juanpa.arrivillaga 8/3/2023 #1

我认为最安全的选择是使用:__qualname__

In [6]: def foo():
   ...:     def bar():
   ...:         def baz():
   ...:             return 42
   ...:         return baz
   ...:     return bar()
   ...:

In [7]: f = foo()

In [8]: f
Out[8]: <function __main__.foo.<locals>.bar.<locals>.baz()>

In [9]:

In [9]: f.__qualname__
Out[9]: 'foo.<locals>.bar.<locals>.baz'

所以,像这样:

In [11]: f.__qualname__.replace("<locals>.", "")
Out[11]: 'foo.bar.baz'