【问题标题】:How can I get the function object inside a lambda function如何在 lambda 函数中获取函数对象
【发布时间】:2022-01-14 18:11:22
【问题描述】:

对不起,如果这很蹩脚,但我对 Python 还是很陌生。

在 Python 中,一切都是对象,我假设在每个对象中,对象本身都可以通过某种方式获得。在对象方法中,self 变量包含它。从对象引用中可以得到类对象(如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 中给出了 &lt;lambda&gt;

有没有办法在 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 对象。

【问题讨论】:

标签: python python-3.x lambda


【解决方案1】:

我们现在可以使用新的 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

【讨论】:

  • 这不是重复的答案!我添加了更多细节并解释了用户的具体用例。我在这里只使用来自另一个问题的两个示例:stackoverflow.com/a/70731695/14580601
【解决方案2】:

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

只有遵循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

【讨论】:

  • 这太棒了!谢谢!我使用了这个lfunc = lambda : gc.get_referrers(inspect.stack()[0].frame.f_code)[0],现在print(lfunc)print(lfunc()) 给出了相同的结果:&lt;function &lt;lambda&gt; at 0x7f8305a02840&gt;!极好的!这也适用于正常功能!
  • 荒谬地很慢,因为它需要搜索整个程序中的每一个被 GC 跟踪的对象。这意味着这个问题在玩具示例程序中不会很明显,但是一旦你有更多的对象,这很快就会变得不可用,即使这些对象与你正在寻找的 lambda 无关。
  • 如果多个函数使用相同的代码对象,它也会失败,在某些情况下与闭包一致,但在多线程程序中也可能不一致,导致难以重现的错误。
  • @flakes 我把它应用到了一个类对象上,我惊讶地得到了一个函数对象!就像:class X(): print(gc.get_referrers(inspect.stack()[0].frame.f_code)[0])。这给出了 function X at 0x7fb7f1c94048>.
  • @user2357112 支持莫妮卡 你说得对!这种方法存在问题。但我的问题是这是否可能,而且确实如此! :) 恕我直言,这是 Python 的一个(不是最大的)问题,它指出一切都是对象,但有时很难在类体内获取 lambda 或类的“自我”指针。也许可以实现某种自动化(如__self__)来支持这一点。但也许我错了……
猜你喜欢
  • 1970-01-01
  • 2017-07-26
  • 1970-01-01
  • 2019-09-29
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多