函数定义与Lambda表达式

时间:2012-12-13 05:12:24

标签: python

鉴于这两个片段:

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

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

实际差异是什么?他们有不同的行为吗?

最重要的是:一个人比另一个好吗?

我问这个问题,因为我在这个论坛中的答案之一(python3 - learning about searching, this very simple example does not work right)提供了两种可能性,被另一个用户(“修订版”)截断,删除了lambda术语。修订的原因是最后一个选项(lambda表达式)比函数定义更差。这让我想知道:

为什么lambda表达式比函数定义更差?特别简单,比如这些。

6 个答案:

答案 0 :(得分:7)

lambda和返回相同内容的def之间没有功能差异。它们完全相同,字节码相同。

>>> 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定义它。

答案 1 :(得分:3)

除了BrenBarn's excellent answer中提供的信息之外,您会发现许多Python程序员坚持始终使用def而不是lambda,因此我将尝试解释原因。< / p>

它基本上归结为Zen of Python

中的以下行
  

应该有一个 - 最好只有一个 - 显而易见的方法。

这在Guido van Rossum's post about this issue中引用(Guido是Python的创建者):

  

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

答案 2 :(得分: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'>

答案 3 :(得分:0)

简单的lambdas不一定比嵌套函数差(不,这两个例子之间没有差别,但是语法),但这种特殊情况甚至可以更简单:

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

然后使用sex.__getitem__

答案 4 :(得分:0)

它们具有相同的行为,但关键区别在于lambda是一个表达式,因此不能包含语句。 lambdas不一定比函数定义更糟糕,只要它们被恰当地使用。但是,它们通常用于编写单行函数,因为它们可以,即使它使代码几乎不可能读取。例如,请考虑以下事项:

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,但是一个非常糟糕的主意!

答案 5 :(得分:0)

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

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