我听说在Python中不能添加多行lambdas,因为它们会在语法上与Python中的其他语法结构冲突。今天在公交车上,我一直在思考这个问题,并意识到我想不出任何一个Python构造可以与多行lambdas相冲突。考虑到我对这门语言相当熟悉,这让我很惊讶。

现在,我相信Guido没有在语言中包含多行lambda是有原因的,但出于好奇:在什么情况下,包含多行lambda会有歧义?我听说的是真的吗,还是有其他原因导致Python不允许多行lambda ?


当前回答

看看下面这些:

map(multilambda x:
      y=x+1
      return y
   , [1,2,3])

这是一个lambda返回(y,[1,2,3])(因此映射只得到一个参数,导致错误)?还是返回y?或者这是语法错误,因为新行上的逗号放错了地方?巨蟒怎么知道你想要什么?

在paren中,缩进对python来说并不重要,因此不能明确地使用多行。

这只是一个简单的例子,可能还有更多的例子。

其他回答

看看下面这些:

map(multilambda x:
      y=x+1
      return y
   , [1,2,3])

这是一个lambda返回(y,[1,2,3])(因此映射只得到一个参数,导致错误)?还是返回y?或者这是语法错误,因为新行上的逗号放错了地方?巨蟒怎么知道你想要什么?

在paren中,缩进对python来说并不重要,因此不能明确地使用多行。

这只是一个简单的例子,可能还有更多的例子。

我很内疚在我的一些更简单的项目中实践了这个肮脏的hack:

    lambda args...:( expr1, expr2, expr3, ...,
            exprN, returnExpr)[-1]

我希望你能找到一种方法保持python化,但如果你必须这样做,这比使用exec和操纵全局变量要少一些痛苦。

在Python3.8之后,还有另一个用于本地绑定的方法

lambda x: (
    y := x + 1,
    y ** 2
)[-1]

For循环

lambda x: (
    y := x ** 2,
    [y := y + x for _ in range(10)],
    y
)[-1]

如果分支

lambda x: (
    y := x ** 2,
    x > 5 and [y := y + x for _ in range(10)],
    y
)[-1]

Or

lambda x: (
    y := x ** 2,
    [y := y + x for _ in range(10)] if x > 5 else None,
    y
)[-1]

While循环

import itertools as it
lambda x: (
    l := dict(y = x ** 2),
    cond := lambda: l['y'] < 100,
    body := lambda: l.update(y = l['y'] + x),
    *it.takewhile(lambda _: cond() and (body(), True)[-1], it.count()),
    l['y']
)[-1]

Or

import itertools as it
from types import SimpleNamespace as ns
lambda x: (
    l := ns(y = x ** 2),
    cond := lambda: l.y < 100,
    body := lambda: vars(l).update(y = l.y + x),
    *it.takewhile(lambda _: cond() and (body(), True)[-1], it.count()),
    l.y
)[-1]

Or

import itertools as it
lambda x: (
    y := x ** 2,
    *it.takewhile(lambda t: t[0],
    ((
    pred := y < 100,
    pred and (y := y + x))
    for _ in it.count())),
    y
)[-1]

这通常是非常丑陋的(但有时替代方案甚至更丑陋),所以一个变通的方法是创建一个大括号表达式:

lambda: (
    doFoo('abc'),
    doBar(123),
    doBaz())

它不会接受任何任务,所以你必须事先准备好数据。 我发现这种方法很有用的地方是PySide包装器,在那里有时会有简短的回调。编写额外的成员函数将更加丑陋。通常你不需要这个。

例子:

pushButtonShowDialog.clicked.connect(
    lambda: (
    field1.clear(),
    spinBox1.setValue(0),
    diag.show())

我从python开始,但来自Javascript的最明显的方式是提取表达式作为函数....

人为的例子,乘法表达式(x*2)被提取为函数,因此我可以使用multiline:

def multiply(x):
  print('I am other line')
  return x*2

r = map(lambda x : multiply(x), [1, 2, 3, 4])
print(list(r))

https://repl.it/@datracka/python-lambda-function

也许它并没有确切地回答这个问题,如果这是如何在lambda表达式本身做多行,但如果有人得到这个线程,看看如何调试表达式(像我),我认为这将有所帮助