是否可以在 Python Lambda 函数中使用非本地函数?

is it possible to have nonlocal in python lambda function?

提问人:datapy 提问时间:10/12/2023 更新时间:10/12/2023 访问量:60

问:

现在我的 lambda 函数是:

In [40]: f=lambda x, count=0: count if not(x%3==0) else count+1

In [41]: [f(x) for x in range(10)]
Out[41]: [1, 0, 0, 1, 0, 0, 1, 0, 0, 1]

但我真正想要的是累积计数,以便输出为:

Out[42]: [1, 1, 1, 2, 2, 2, 3, 3, 3, 4]

我正在寻找一些代码,例如:

f=lambda x, count=0: nonlocal count if not(x%3==0) else count+1

但收到使用“nonlocal”的语法错误消息。所以我的问题是:有没有办法在 lambda 中定义非局部变量?

Python Lambda 闭包

评论

2赞 Barmar 10/12/2023
函数参数永远不能是 或 。globalnonlocal
0赞 Barmar 10/12/2023
为什么不直接创建一个命名函数?def
2赞 Barmar 10/12/2023
会有什么帮助?这只对你赋值的变量有意义,但你不能在 lambda 中进行变量赋值(尽管我认为使用 walrus 运算符有一些技巧)。nonlocal
3赞 Suraj Shourie 10/12/2023
我觉得你正在成为XY问题的牺牲品。 如果你只是想累积计数,这样的东西也可以[(x // 3 )+ 1 for x in range(10)]
4赞 Barmar 10/12/2023
简单的答案是你没有。

答:

2赞 juanpa.arrivillaga 10/12/2023 #1

通常,lambda 函数应该是纯函数,这就是为什么它们被故意限制为表达式的原因。

因此,您不能在 lambda 表达式中赋值给非局部/全局变量(尽管您可以使用赋值表达式赋值给局部变量)。

如果使用 / 并赋值给变量,则始终只能使用函数定义语句。您永远不必使用 lambda 表达式来创建函数。lambda 表达式的功能受到有意限制。如果您想要更多的东西,只需使用函数定义语句即可。nonlocalglobal

但在这种情况下,你不应该这样做 在这种情况下,你正在尝试使用列表推导来产生副作用。这通常令人困惑,并被认为是一种反模式。最好直接使用 for 循环:

result = []
count = 0
for i in range(10):
    if i%3 == 0:
        count += 1
    result.append(count)

这是完美的pythonic。

但是,如果您想要一种更实用的编程方法,则应使用:itertools.accumulate

import itertools
result = itertools.accumulate(map(lambda x: int(x%3 == 0), range(10)))

Lambda 表达式不能包含类似 或 的语句。但是您应该为这项工作选择正确的工具,在这种情况下,它要么只是一个普通的 for 循环,要么 .nonlocalglobalitertools.accumualte

0赞 skxxtz 10/12/2023 #2

如果您确实必须使用 lambda 函数来执行此操作,您可以尝试以下操作:

count = 0
f = lambda x: (setattr(f, 'count', getattr(f, 'count', 0) + 1) if x % 3 == 0 else None, f.count)[1]

print([f(x) for x in range(10)])

不过,我建议再次这样做。这些家伙给了你一些比 lambda 更好的选择......