Python 与 Ruby 相比的限制:lambda

发布于 2024-08-29 08:02:59 字数 175 浏览 7 评论 0原文

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

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

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

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

I was going over some pages from WikiVS, that I quote from:

because lambdas in Python are restricted to expressions and cannot
contain statements

I would like to know what would be a good example (or more) where this restriction would be, preferably compared to the Ruby language.

Thank you for your answers, comments and feedback!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

电影里的梦 2024-09-05 08:02:59

我认为您并不是真正在问 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();

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

我可能会将其视为日常 Python 中最烦人的限制。

I don't think you're really asking about lambdas, but inline functions.

This is genuinely one of Python's seriously annoying limitations: you can't define a function (a real function, not just an expression) inline; you have to give it a name. This is very frustrating, since every other modern scripting language does this and it's often very painful to have to move functions out-of-line. It's also frustrating because I have a feeling Python bytecode can represent this trivially--it's just the language syntax that can't.

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"]()

Note that JavaScript and Lua don't have lambdas: they have no reason to exist, since inline functions cover them in a much more natural and general way.

I'd probably rate this as the single most annoying day-to-day Python limitation.

坦然微笑 2024-09-05 08:02:59

关于语句最常遇到的情况可能是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
                 |断言_stmt
                 |分配_stmt
                 |增强分配_stmt
                 | pass_stmt
                 |删除stmt
                 |打印_stmt
                 |返回_stmt
                 |产量_stmt
                 | raise_stmt
                 |中断_stmt
                 |继续_stmt
                 |导入_stmt
                 |全局_stmt
                 |执行命令

如果您想看到它们失败,您可以在 REPL 中尝试其余的内容:

>> assert(True)
>>> assert_lambda = lambda: assert(True)
SyntaxError: invalid syntax
>>> pass
>>> pass_lambda = lambda: pass
SyntaxError: invalid syntax

我不确定 Python 的 lambda 限制和 Ruby 的 proc 或拉姆达。在 Ruby 中,一切都是消息,所以你没有关键字(好吧,你确实有关键字,但是你没有像 Python 的 print 这样的函数的关键字代码>)。我突然想到,没有任何容易出错的 Ruby 结构会在 proc 中失败。

The most commonly encountered situation regarding statements is probably Python 2.X's print statement.

For example,

say_hi = lambda name: "Hello " + name

works as expected.

But this will not compile:

say_hi = lambda name: print "Hello " + name

because print is not a proper function in Python 2.

>>> say_hi = lambda name: "Hello " + name
>>> say_hi("Mark")
'Hello Mark'
>>> 
>>> say_hi = lambda name: print "Hello " + name
SyntaxError: invalid syntax

The rest of the statements besides print can be found 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

You can try the rest of these out in the REPL if you want to see them fail:

>> assert(True)
>>> assert_lambda = lambda: assert(True)
SyntaxError: invalid syntax
>>> pass
>>> pass_lambda = lambda: pass
SyntaxError: invalid syntax

I'm not sure what parallels there are between Python's lambda restrictions and Ruby's proc or lambda. In Ruby, everything is a message, so you don't have keywords (okay, you do have keywords, but you don't have keywords that appear to be functions like Python's print). Off the top of my head, there's no easily-mistaken Ruby constructs that will fail in a proc.

哀由 2024-09-05 08:02:59

我有时会想到一个这样的例子:

def convert(value):
    n = expensive_op(value)
    return (n, n + 1)

new_list = map(convert, old_list)

虽然它足够短且足够好,但你不能将它转换为 lambda,而无需运行 expense_op() 两次(这,如顾名思义,你不想这样做),即你必须这样做,

new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list)

因为赋值 (n = ...) 是一个语句。

An example that has sometimes come up with me is something like this:

def convert(value):
    n = expensive_op(value)
    return (n, n + 1)

new_list = map(convert, old_list)

Although it is short and sweet enough, you can't convert it to a lambda without having to run expensive_op() twice (which, as the name suggests, you don't want to), i.e. you would have to do

new_list = map(lambda v: (expensive_op(v), expensive_op(v) + 1), old_list)

because assignment (n = ...) is a statement.

冰火雁神 2024-09-05 08:02:59

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

Instead of f=lambda s:pass you can do f=lambda s:None.

Bonjour°[大白 2024-09-05 08:02:59

lambda 只是 Python 中定义返回简单表达式的函数的快捷方式。
这并不是任何有意义的限制。如果您需要多个表达式,那么只需使用函数即可:使用 lambda 可以做的事情没有,而函数则无法做到。

使用函数而不是 lambda 的唯一缺点是该函数必须在 1 个或多个单独的行上定义(因此与 lambda 相比,您可能会失去一些局部性),并且您必须为该函数发明一个名称(但是如果你想不出一个那么 f 通常可以工作)。

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

使用命名函数的一大优点当然是,当它出错时,您可以获得有意义的堆栈跟踪。昨天,当我得到一个涉及 lambda 的堆栈跟踪并且没有关于它是哪个 lambda 的上下文时,我就遇到了这个问题。

lambda is simply a shortcut way in Python to define a function that returns a simple expression.
This isn't a restriction in any meaningful way. If you need more than a single expression then just use a function: there is nothing you can do with a lambda that you cannot do with a function.

The only disadvantages to using a function instead of a lambda are that the function has to be defined on 1 or more separate lines (so you may lose some locality compared to the lambda), and you have to invent a name for the function (but if you can't think of one then f generally works).

All the other reasons people think they have to use a lambda (such as accessing nested variables or generating lots of lambdas with separate default arguments) will work just as well with a function.

The big advantage of using a named function is of course that when it goes wrong you get a meaningful stack trace. I had that bite me yesterday when I got a stack trace involving a lambda and no context about which lambda it was.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文