1

鉴于这两个片段:

def sex (code):
    return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

sex = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

实际的区别是什么?他们有不同的行为吗?

最重要的是:一个比另一个更可取吗?

我问这个,因为我在这个论坛上的一个答案(python3 - 学习搜索,这个非常简单的例子不能正常工作),它提供了两种可能性,被另一个用户截断(“修订”),删除了 lambda 术语。修改的原因是最后一个选项(lambda 表达式)比函数定义差。这让我想知道:

为什么 lambda 表达式比函数定义差?尤其是像这样的简单的。

4

6 回答 6

7

deflambda 和返回相同内容的a 在功能上没有区别。它们完全相同并且具有相同的字节码。

>>> def sex (code):
...     return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> sex2 = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> sex.__code__.co_code == sex2.__code__.co_code
True

我会说在一般意义上说任何一种编写函数的方式都“更糟”是错误的。但是,在您的示例中,def版本更好。原因是,通常 lambdas 的目的是在表达式中简洁地编写简短的匿名函数。这样做没有真正意义name = lambda: ...。如果您要立即为其命名,则没有理由定义匿名函数。

lambdas 的重点是你可以做someFuncRequiringCallback(lambda x: x+1),除了这种情况,你不想给函数命名或将它用于任何事情。如果您确实想在多个上下文中使用函数,只需使用常规定义它即可def

于 2012-12-13T05:15:40.023 回答
3

除了BrenBarn 的优秀答案中提供的信息之外,您会发现许多 Python 程序员坚持总是使用defover lambda,所以我将尝试解释为什么会这样。

它基本上归结为Python Zen的以下行:

应该有一种——最好只有一种——明显的方法来做到这一点。

这在Guido van Rossum 关于这个问题的帖子中被引用(Guido 是 Python 的创建者):

为什么要放弃 lambda?大多数 Python 用户对 Lisp 或 Scheme 不熟悉,因此名称令人困惑;此外,还有一个普遍的误解,即 lambda 可以做嵌套函数不能做的事情——在我向她展示没有区别之后,我仍然记得 Laura Creighton 的 Aha!-erlebnis!即使有一个更好的名字,我认为同时拥有这两个选择只是要求程序员考虑做出与他们的程序无关的选择;没有选择可以简化思考过程。此外,一旦 map()、filter() 和 reduce() 消失,就没有很多地方真正需要编写非常短的局部函数了。想到了 Tkinter 回调,但我发现回调通常应该是一些带有状态的对象的方法(玩具程序除外)。

于 2012-12-13T05:31:52.183 回答
3

都是一样的,查看反汇编的python字节码

>>> def sex1 (code):
    return {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]

>>> sex2 = lambda code: {'m': 'masculino', 'f': 'femenino', '': 'ignorado'} [code]
>>> dis.dis(sex1)
  2           0 BUILD_MAP                3
              3 LOAD_CONST               1 ('masculino')
              6 LOAD_CONST               2 ('m')
              9 STORE_MAP           
             10 LOAD_CONST               3 ('femenino')
             13 LOAD_CONST               4 ('f')
             16 STORE_MAP           
             17 LOAD_CONST               5 ('ignorado')
             20 LOAD_CONST               6 ('')
             23 STORE_MAP           
             24 LOAD_FAST                0 (code)
             27 BINARY_SUBSCR       
             28 RETURN_VALUE        
>>> dis.dis(sex2)
  1           0 BUILD_MAP                3
              3 LOAD_CONST               1 ('masculino')
              6 LOAD_CONST               2 ('m')
              9 STORE_MAP           
             10 LOAD_CONST               3 ('femenino')
             13 LOAD_CONST               4 ('f')
             16 STORE_MAP           
             17 LOAD_CONST               5 ('ignorado')
             20 LOAD_CONST               6 ('')
             23 STORE_MAP           
             24 LOAD_FAST                0 (code)
             27 BINARY_SUBSCR       
             28 RETURN_VALUE    

甚至它们都具有相同的类型

>>> type(sex1)
<type 'function'>
>>> type(sex2)
<type 'function'>
于 2012-12-13T05:54:54.937 回答
0

简单的 lambda 不一定比嵌套函数差(不,这两个示例之间没有区别,但语法不同),但这种特殊情况可能更简单:

sex = {'m': 'masculino', 'f': 'femenino', '': 'ignorado'}

然后你使用sex.__getitem__.

于 2012-12-13T05:15:59.533 回答
0

它们具有相同的行为,但主要区别在于 lambda 是一个表达式,因此不能包含语句。lambda 不一定比函数定义差,只要它们使用得当。然而,它们经常被用来编写单行函数,只是因为它们可以,即使它使代码实际上无法阅读。例如,考虑以下情况:

sortfilter = lambda a, b, c: sorted(filter(lambda i: i % 2, (i for i in a if i in b)), key=lambda v: c.get(v, v)))

可以用单行 lambda 编写,但这是一个非常糟糕的主意!

于 2012-12-13T05:33:34.870 回答
0

它有助于区分事物。如果我要定义一个函数,我将从 def 开始,但是在该函数内部我通常会使用 lambda。

这与用英语写作的概念相同。如果报价正在引用报价,您将需要更改嵌套报价的外观。括号也是如此。

于 2015-05-21T10:32:07.503 回答