与Ruby相比,Python的限制:lambdas

时间:2010-04-16 16:02:50

标签: python ruby lambda restriction

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

  

因为Python中的lambdas仅限于表达式而不能   包含陈述

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

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

5 个答案:

答案 0 :(得分:12)

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

这真的是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();

红宝石:

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限制。

答案 1 :(得分:9)

关于语句最常遇到的情况可能是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以外的其他陈述可以找到in the Python documentation online

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中失败。

答案 2 :(得分:4)

有时提出我的一个例子是这样的:

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 = ...)是一个陈述。

答案 3 :(得分:2)

而不是f=lambda s:pass,您可以f=lambda s:None

答案 4 :(得分:1)

lambda只是Python中一种快捷方式,用于定义返回简单表达式的函数。 这不是任何有意义的限制。如果您需要多个表达式,那么只需使用一个函数: nothing 可以使用函数无法执行的lambda。

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

人们认为他们必须使用lambda的所有其他原因(例如访问嵌套变量或使用单独的默认参数生成大量lambda)也可以与函数一起使用。

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