如何在 lambda 函数中获取函数对象

How can I get the function object inside a lambda function

抱歉,如果这很蹩脚,但我是 Python 的新手。

正如在 Python 中一样,一切都是对象,我假设在每个对象中,对象本身都可以通过某种方式获得。在对象方法中,self 变量包含它。从对象引用中可以得到 class 对象(如 type(self))。但是如何将其放入 lambda 中?

我可以算出一个正常的函数:

import inspect

def named_func():
    func_name = inspect.stack()[0].function
    func_obj = inspect.stack()[1].frame.f_locals[func_name]
    print(func_name, func_obj, func_obj.xxx)

named_func.xxx = 15
named_func()

输出如下所示:

named_func <function named_func at 0x7f56e368c2f0> 15

不幸的是,在 lambda 中 inspect.stack()[0].function 在 lambda 内部给出了 <lambda>

有没有办法在 lambda 中获取函数对象? 有没有办法直接获取函数对象(不使用函数名称)? 我想象的__self__,但是不行

更新

我在 lambda 中尝试过这样的事情:

lambda_func = lambda : inspect.stack()[0]
lambda_func.xxx = 2
print(lambda_func())

这会打印:

FrameInfo(frame=<frame at 0x7f3eee8a6378, file './test_obj.py', line 74, code <lambda>>, filename='./test_obj.py', lineno=74, function='<lambda>', code_context=['lambda_func = lambda : inspect.stack()[0]\n'], index=0)

但是例如,在这种情况下有没有办法获取 lambda 对象字段 xxx?为此,应该以某种方式获取 lambda 对象。

注意,这不是问题的 efficient/pragmatic 解决方案。这不是关于如何编写实际软件的建议。它只是介绍如何在不将其分配给变量名的情况下从 lambda 访问 lambda 引用。这是一个非常hacky的答案。

只有遵循 answer found here

的建议才能完全正确地工作

简而言之,给定 stack 你可以找到 code 对象,然后使用 gc 模块你可以找到对你的 lambda 的引用。

@Tomalak 的阶乘 lambda 示例!

import gc
import inspect


def current_lambda():
    lambda_code = inspect.stack()[1].frame.f_code
    candidates = [
        referrer
        for referrer in gc.get_referrers(lambda_code)
        if inspect.isfunction(referrer)
        and referrer.__code__ is lambda_code
    ]
    if len(candidates) != 1:
        raise ValueError(
            "Multiple candidates found! Cannot determine correct function!"
        )
    return candidates[0]


print((lambda n: 1 if n < 2 else n * current_lambda()(n - 1))(5))

产出

120

回顾你的例子:

lambda_func = lambda: current_lambda().xxx
lambda_func.xxx = 10
print(lambda_func())

输出:

10

我们现在可以使用新的 python 语法使其更短且更易于阅读,而无需为此目的定义新函数。

您可以在下面找到两个示例:

斐波那契数列:

(f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)

阶乘:

(f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)

我们使用 := 命名 lambda:直接在 lambda 本身中使用该名称,并立即将其作为匿名函数调用。

所以在你的特定用例中它会给出类似的东西:

print((f:=lambda: f.__hash__())())  # prints the hash for example

您现在可以使用 f 变量(在 lambda 中)做任何您想做的事情。

但实际上,如果您不介意代码多行,您也可以直接使用名称并执行类似的操作:

f = lambda : f.xxx
f.xxx = 2
print(f())

(有关此 := 运算符的更多信息,请参阅 https://www.python.org/dev/peps/pep-0572