我听到有人说,多行lambda表达式不能在Python中添加,因为他们会在Python中的其它语法结构语法冲突。我今天在公共汽车上考虑这一点,并意识到我不能想象一个Python的构建多lambda表达式与冲突。鉴于我知道的语言很好,这让我感到惊讶。
现在,我敢肯定圭多了不包括在语言多行lambda表达式的一个原因,但出于好奇:什么是其中包括一个多拉姆达是模棱两可的情况?是我所听到的真实,或者是有一些其他原因的Python不允许lambda表达式多?
请看下面:
map(multilambda x:
y=x+1
return y
, [1,2,3])
这是一个lambda返回(y, [1,2,3])
(因此映射只得到一个参数,从而导致错误)?或者它返回y
?或者是一个语法错误,因为在新行逗号放错了地方? Python的怎么会知道你想要什么?
在括号内的,压痕不要紧,蟒蛇,所以你不能明显与多线工作。
这仅仅是一个简单的,有可能是更多的例子。
在丑陋的黑客的问题,您可以随时使用exec
的组合和常规的功能来定义这样的多的功能:
f = exec('''
def mlambda(x, y):
d = y - x
return d * d
''', globals()) or mlambda
您可以封装成函数此类似:
def mlambda(signature, *lines):
exec_vars = {}
exec('def mlambda' + signature + ':\n' + '\n'.join('\t' + line for line in lines), exec_vars)
return exec_vars['mlambda']
f = mlambda('(x, y)',
'd = y - x',
'return d * d')
我只是打了一下,要尽量做到与减少的字典理解,并拿出这一个班轮黑客:
In [1]: from functools import reduce
In [2]: reduce(lambda d, i: (i[0] < 7 and d.__setitem__(*i[::-1]), d)[-1], [{}, *{1:2, 3:4, 5:6, 7:8}.items()])
Out[3]: {2: 1, 4: 3, 6: 5}
我只是试图做一样的东西在此Javascript字典理解做:https://stackoverflow.com/a/11068265
因为lambda函数应该是一个衬里,作为其功能,an entrance, then return
的最简单的形式
吉多·范罗苏姆(Python中的发明人)回答了这个问题询问自己在an old blog post。 基本上,他承认,它在理论上是可能的,但是,任何建议的解决办法是联合国Python化:
“但对于这个难题提出的任何解决方案的复杂性是巨大的,对我说:它要求解析器(或者更准确地说,词法分析器),以便能够缩进敏感和缩进不敏感的模式之间来回切换,保持一个堆栈以前的模式和缩进的水平。从技术上说都可以解决了(已经有可能被推广缩进层次的堆叠),但这些方法都带走了我的直觉,这是所有精心Rube Goldberg contraption“。
这通常是非常难看(但有时替代品就更难看了),所以解决方法是做一个括号表达式:
lambda: (
doFoo('abc'),
doBar(123),
doBaz())
它不会接受任何分配的,所以你必须事先准备数据。我发现这个有用的地方是PySide包装,你有时有短暂回调。编写额外的成员函数会更加难看。通常情况下,你不需要这个。
例:
pushButtonShowDialog.clicked.connect(
lambda: (
field1.clear(),
spinBox1.setValue(0),
diag.show())
一对夫妇相关链接:
有一段时间,我在下面的区域环境影响评价,这是最初将拥有Python的缩进基于使用Ruby语法的块太大,所有对二郎的顶部发展。但是,设计师卷筒上的压痕敏感性放弃,而这后,他写了一篇关于这一决定包括关于他遇到了与缩进+多行块问题的讨论,并且他的对圭多的设计议题/决定增加欣赏:
http://www.unlimitednovelty.com/2009/03/indentation-sensitivity-post-mortem.html
此外,这里是一个Ruby风情的街区在Python我碰到哪里圭多张贴的响应跑了一个有趣的建议,W / O实际拍摄下来(不知道是否有任何后续拍下来,虽然):
让我给你介绍一个光荣的,但可怕的黑客:
import types
def _obj():
return lambda: None
def LET(bindings, body, env=None):
'''Introduce local bindings.
ex: LET(('a', 1,
'b', 2),
lambda o: [o.a, o.b])
gives: [1, 2]
Bindings down the chain can depend on
the ones above them through a lambda.
ex: LET(('a', 1,
'b', lambda o: o.a + 1),
lambda o: o.b)
gives: 2
'''
if len(bindings) == 0:
return body(env)
env = env or _obj()
k, v = bindings[:2]
if isinstance(v, types.FunctionType):
v = v(env)
setattr(env, k, v)
return LET(bindings[2:], body, env)
现在,您可以使用此LET
形式,例如:
map(lambda x: LET(('y', x + 1,
'z', x - 1),
lambda o: o.y * o.z),
[1, 2, 3])
这给:[0, 3, 8]
[编辑]读this answer.它解释了为什么多拉姆达不是一回事。
简单地说,它是unpythonic。从吉多·范罗苏姆的博客文章:
我发现不可接受的任何解决方案,嵌入在一个表达式的中间基于压痕块。由于我找到声明分组替换语法(例如括号或开始/结束关键字)同样不能接受,这几乎使多行拉姆达一个无法解决的难题。
对于这个答案的其余部分。无论是使用单一号线的λ或命名功能。请不要使用exec
- 我后悔曾经建议。
1You'd惊讶,你可以使用Python的一行做什么。
一种解决方法以获得多lambda函数(延期skriticos的答案):
(lambda n: (exec('global x; x=4; x=x+n'), x-2)[-1])(0)
它能做什么:
lambda x: (functionA(), functionB(), functionC(), 0)[-1]
将执行所有三个功能。exec
功能,您可以(注意,它总是返回:None
)在python列表或元组内声明变量。global
它不会对exec
函数调用的外部存在(这只是针对exec
语句中lambda
功能真)。(lambda: exec('x=5;print(x)'))()
作品,未经global
声明的罚款。然而,(lambda: (exec('x=5'), exec('print(x)')))()
或(lambda: (exec('x=5'), x)()
没有。global
变量存储在全局命名空间,并会继续存在函数调用完成后。出于这个原因,这不是一个很好的解决方案,并应在一切可能避免,如果。
从一个lambda函数内部global
函数声明exec
变量保持从global
命名空间是分开的。 (在Python 3.3.3测试)[-1]
得到最后一个索引。例如[1,2,3,4][-1]
是4
。这样做以便仅所希望的输出值(一个或多个)被返回,而不是含有来自None
功能和其它外来的值exec
整个元组。相当于多线功能:
def function(n):
x = 4
x = x+n
return x-2
function(0)
如何避免需要多行拉姆达:
递归:
f = lambda i: 1 if i==0 or i==1 else f(i-1)+f(i-2)
布尔是整数:
lambda a, b: [(0, 9), (2, 3)][a<4][b>3]
迭代器:
lambda x: [n**2 for n in x] #Assuming x is a list or tuple in this case
让我尝试解决@balpha解析问题。我会用括号围绕多LAMDA。如果没有括号,拉姆达的定义是贪婪的。所以在拉姆达
map(lambda x:
y = x+1
z = x-1
y*z,
[1,2,3]))
返回返回(y*z, [1,2,3])
功能
但
map((lambda x:
y = x+1
z = x-1
y*z)
,[1,2,3]))
手段
map(func, [1,2,3])
其中FUNC是多拉姆达返回Ÿ* Z。那样有用吗?
(对于任何人的话题仍然有兴趣。)
考虑这一点(甚至包括了‘多行’拉姆达内进一步的陈述的返回值的使用,虽然它的丑陋呕吐;-)点
>>> def foo(arg):
... result = arg * 2;
... print "foo(" + str(arg) + ") called: " + str(result);
... return result;
...
>>> f = lambda a, b, state=[]: [
... state.append(foo(a)),
... state.append(foo(b)),
... state.append(foo(state[0] + state[1])),
... state[-1]
... ][-1];
>>> f(1, 2);
foo(1) called: 2
foo(2) called: 4
foo(6) called: 12
12
我有罪练习中我的一些项目,这个肮脏的黑客是有点简单的:
lambda args...:( expr1, expr2, expr3, ...,
exprN, returnExpr)[-1]
我希望你能找到一种方式留Python的,但如果你必须这样做,这比使用EXEC和操纵全局的痛苦。