与Ruby相比,Python的限制:lambda

我正在浏览WikiVS的一些页面,我引用了:

因为Python中的lambdas仅限于表达式,不能包含语句

我想知道这个限制将是一个很好的例子(或更多),最好是与Ruby语言相比较。

感谢您的回答,评论和反馈!

我不认为你真的在问lambdas,而是内联函数

这真的是Python严重烦人的限制之一:你无法定义内联函数(一个真正的函数,而不仅仅是一个表达式); 你必须给它一个名字。 这非常令人沮丧,因为其他所有现代脚本语言都是这样做的,并且必须将函数移到线外非常痛苦。 这也令人沮丧,因为我觉得Python字节码可以代表这一点 – 这只是语言语法不能。

使用Javascript:

responses = { "resp1": { "start": function() { ... }, "stop": function() { ... }, }, "resp2": { "start": function() { ... }, "stop": function() { ... }, }, ... } responses["resp1"]["start"](); 

LUA:

 responses = { resp1 = { start = function() ... end; end = function() ... end; }; ... } responses.resp1.start(); 

ruby:

 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没有lambdas:它们没有理由存在,因为内联函数以更加自然和通用的方式覆盖它们。

我可能会认为这是最令人烦恼的日常Python限制。

关于语句最常遇到的情况可能是Python 2.X的print语句。

例如,

 say_hi = lambda name: "Hello " + name 

按预期工作。

但这不会编译:

 say_hi = lambda name: print "Hello " + name 

因为在Python 2中print不是一个合适的function。

 >>> 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的proclambda之间有什么相似之处。 在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) 

因为赋值( n = ... )是一个陈述。

而不是f=lambda s:pass你可以做f=lambda s:None

lambda只是Python中一种快捷方式,用于定义返回简单表达式的函数。 这不是任何有意义的限制。 如果你需要不止一个表达式,那么只需使用一个函数:没有什么可以用lambda做的,你不能用函数做。

使用函数而不是lambda的唯一缺点是函数必须在一个或多个单独的行上定义(因此与lambda相比可能会丢失一些局部性),并且必须为函数创建一个名称(但是如果你想不到一个,那么f一般都有效)。

人们认为他们必须使用lambda的所有其他原因(例如访问嵌套变量或使用单独的默认参数生成大量lambda)将同样适用于函数。

使用命名函数的最大优点当然是当它出错时,你会得到一个有意义的堆栈跟踪。 昨天当我得到一个涉及lambda的堆栈跟踪并且没有关于哪个lambda的上下文时,我曾经咬过我。