本文用于练习英文阅读,如有侵权,联系删除
原文链接是Dan Bader的 Lambda Functions in Python: What Are They Good For?
以下为译文
Python lambda 表达式: 它们的优点,何时使用以及何时最好避免使用他们。
Python中的lambda关键词提供了声明简短匿名函数的快捷方式。Lambda 函数的行为就像使用def关键字声明的常规函数一样。只要函数对象被声明就可以使用。
例如,这是定义一个加法功能的简单lambda函数:
1 | lambda x, y: x + y add = |
你也可以使用def关键字声明同样的加法函数:
1 | def add(x, y): |
现在你可能感到惊奇:为什么对lambdas大惊小怪?如果它只是def声明函数的简洁版,有什么大不了的?
看下面这个例子,并把执行这个操作时把这个函数表达式放在脑海里:
1 | lambda x, y: x + y)(5, 3) ( |
好的,这是怎么回事?我只是用lambda内联定义了一个add 函数,接着用参数5和3进行了调用。
从概念上讲lambda表达式 lambda x,y:x+y 和用def声明的函数类似,只是用了内联写法。区别在于使用它之前没有绑定到诸如add这样的名称上。我只是说了我想计算的表达式,接着像常规函数一样调用它立刻求值。
在你继续之前,你可能需要玩味一下前面的代码示例,以便真的理解它的意思。我仍然记得这花了好久去思考。所以要担心花费几分钟去理解它。
lambdas 和常规函数的另一个语法不同在于:Lamdba 只能是单个表达式。这意味着lambda函数不能使用声明和注释,甚至return语句。
那么该如何使lambdas返回值?执行lambda函数会评估其表达式,然后自动返回结果。因此,总会有一个隐式的return语句。这就是为什么有些人将lambda称为单表达式函数的原因。
Lambda的使用
什么时候你可以使用lambda函数在你的代码中?从技术上讲,任何只要希望提供函数对象的时候都可以使用lambda表达式。并且因为lambda表达式是可以匿名的,你甚至不需要声明它。
这提供一个方便的非官方的快捷定义Python函数的方法。我最常用到的lambda示例是按照指定键指定规则进行排序:
1 | sorted(range(-5, 6), key=lambda x: x ** 2) |
像常规函数一样,lambda也可以用作词法闭包。
什么是词法闭包?只是对一种特殊的函数功能的称呼。即使程序流不再位于该作用域,他也能记住封闭的词法作用域的值。这是一个(很学术)的例子来说明这个想法:
1 | def make_adder(n): |
在上面例子中 即使 lambda x+n 包含在 make_adder 函数的的作用域中,仍然可以访问n的值。
有时,使用lambda函数代替使用def声明的嵌套函数可以更清晰地表达自己的意图。但是,老实说这并不常见————至少我很少这么写代码。
不滥用Lambda
现在,一方面,我希望本文使你对Python lambda函数感兴趣。另一方面,我觉得需要提出一个警告:Lambda 函数应该被谨慎使用。
我知道,我使用了lambda表达式编写了一部分看起来“很酷”的代码,但是这对我和我的同事通常是一个负担。如果你想使用lambda,请花几秒(或几分钟)去思考这是否是干净可维护的代码。
例如,写这样的两行代码去保存变量值是愚蠢的。当然,从技术上讲它是有效的,并且是个很好的“技巧”。但是这会让下一个在有限时间内维护它的人感到困惑:
1 | # Harmful: |
使用复杂的map() 或 filter() 会让我产生和使用lambda相同的困惑。通常用list生成式或生成器会更干净:
1 | # 糟糕的: |
如果你发现自己使用一个复杂的lambda表达式,请考虑用合适的名称定义一个函数代替它。
从长远来看,节省一些键盘敲击无关紧要。你的同事(和将来的你)更喜欢干净易读的代码。
要记住的事情
- Lambda 函数不必绑定命名(匿名)
- Lambda 不能使用常规的Python语句,并且始终包含隐式的return语句
- 总是问自己: 使用常规(命名)函数或生成器是否会更清晰。