我正在浏览 WikiVS 的一些页面,我引用了这些页面:
因为 Python 中的 lambda 仅限于表达式,不能包含语句
我想知道这个限制在哪里是一个很好的例子(或更多),最好是与 Ruby 语言相比。
感谢您的回答、评论和反馈!
我正在浏览 WikiVS 的一些页面,我引用了这些页面:
因为 Python 中的 lambda 仅限于表达式,不能包含语句
我想知道这个限制在哪里是一个很好的例子(或更多),最好是与 Ruby 语言相比。
感谢您的回答、评论和反馈!
我不认为你真的在问 lambdas,而是在问内联函数。
这确实是 Python 非常恼人的限制之一:你不能内联定义一个函数(一个真正的函数,而不仅仅是一个表达式);你必须给它一个名字。这是非常令人沮丧的,因为所有其他现代脚本语言都会这样做,并且不得不将函数移出线外通常是非常痛苦的。这也令人沮丧,因为我感觉 Python 字节码可以简单地表示这一点——只是语言语法不能。
Javascript:
responses = {
"resp1": {
"start": function() { ... },
"stop": function() { ... },
},
"resp2": {
"start": function() { ... },
"stop": function() { ... },
},
...
}
responses["resp1"]["start"]();
卢阿:
responses = {
resp1 = {
start = function() ... end;
end = function() ... end;
};
...
}
responses.resp1.start();
红宝石:
responses = {
"resp1" => {
"start" => lambda { },
"stop" => lambda { },
},
}
responses["resp1"]["start"].call
Python:
def resp1_start():
pass
def resp1_stop():
pass
responses = {
"resp1": {
"start": resp1_start,
"stop": resp1_stop,
},
}
responses["resp1"]["start"]()
请注意,JavaScript 和 Lua 没有 lambda:它们没有理由存在,因为内联函数以更自然和通用的方式覆盖它们。
我可能会将其评为最烦人的日常 Python 限制。
最常遇到的关于语句的情况可能是 Python 2.X 的print
语句。
例如,
say_hi = lambda name: "Hello " + name
按预期工作。
但这不会编译:
say_hi = lambda name: print "Hello " + name
因为print
在 Python 2 中不是一个合适的函数。
>>> say_hi = lambda name: "Hello " + name
>>> say_hi("Mark")
'Hello Mark'
>>>
>>> say_hi = lambda name: print "Hello " + name
SyntaxError: invalid syntax
其余的语句print
可以在 Python 在线文档中找到:
simple_stmt ::= expression_stmt | assert_stmt | assignment_stmt | augmented_assignment_stmt | pass_stmt | del_stmt | print_stmt | return_stmt | yield_stmt | raise_stmt | break_stmt | continue_stmt | import_stmt | global_stmt | exec_stmt
如果你想看到它们失败,你可以在 REPL 中尝试其余的:
>> assert(True)
>>> assert_lambda = lambda: assert(True)
SyntaxError: invalid syntax
>>> pass
>>> pass_lambda = lambda: pass
SyntaxError: invalid syntax
我不确定 Python 的lambda
限制和 Ruby 的proc
或lambda
. 在 Ruby 中,一切都是消息,因此您没有关键字(好吧,您确实有关键字,但没有关键字看起来像 Python 的函数print
)。在我的脑海中,没有容易被误解的 Ruby 结构会在proc
.
我有时想到的一个例子是这样的:
def convert(value):
n = expensive_op(value)
return (n, n + 1)
new_list = map(convert, old_list)
虽然它足够简短和甜美,但你不能将它转换为 lambda 而不必运行expensive_op()
两次(顾名思义,你不想这样做),即你必须这样做
new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list)
因为 assignment ( n = ...
) 是一个语句。
而不是f=lambda s:pass
你可以做的f=lambda s:None
。
lambda
只是 Python 中定义返回简单表达式的函数的一种快捷方式。这不是任何有意义的限制。如果您需要的不仅仅是一个表达式,那么只需使用一个函数:对于lambda,没有什么是您无法使用函数做的。
使用函数而不是 lambda 的唯一缺点是该函数必须在 1 个或多个单独的行上定义(因此与 lambda 相比,您可能会失去一些局部性),并且您必须为函数发明一个名称(但是如果你想不出一个,那么f
通常可以工作)。
人们认为他们必须使用 lambda 的所有其他原因(例如访问嵌套变量或使用单独的默认参数生成大量 lambda)都可以与函数一起使用。
使用命名函数的最大优势当然是当它出错时,您可以获得有意义的堆栈跟踪。昨天当我得到一个涉及 lambda 的堆栈跟踪并且没有关于它是哪个 lambda 的上下文时,我被我咬了。