113 lines
4.7 KiB
Markdown
113 lines
4.7 KiB
Markdown
|
|
# Python 中的 Lambda 函数语法(内联函数)
|
|||
|
|
|
|||
|
|
> 原文:<https://www.pythoncentral.io/lambda-function-syntax-inline-functions-in-python/>
|
|||
|
|
|
|||
|
|
Python 的语法相对方便且易于使用,但是除了语言的基本结构之外,Python 还附带了一些小的语法结构,使得某些任务特别方便。关键字/函数结构就是其中之一,创造者称之为“语法糖果”。在这里,我们将研究如何使用它们。
|
|||
|
|
|
|||
|
|
为了理解`lambda`关键字/函数及其构造,我们必须首先回顾一下 Python 中正则函数定义的工作方式。下面是函数定义的基本结构:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
def basic(arg):
|
|||
|
|
|
|||
|
|
# Or whatever the function does
|
|||
|
|
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
# Or whatever the function returns
|
|||
|
|
|
|||
|
|
return arg
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
我们在这里定义的本质上是一个名为 *basic* 的空函数,它接收一个参数,什么也不做(pass 语句本质上是一个有效的“什么也不做”语句),然后返回给它的参数。这是大多数函数最基本的结构,但是最简单的*函数定义将只包含这些语句中的一个——在一个语句中,它要么做某事(或传递),要么返回某事或`None`(一个`return`语句总是至少返回`None`实例,所以它实际上不能返回任何东西)。下面是这两种情况的样子:*
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
def simple1(arg): pass
|
|||
|
|
|
|||
|
|
def simple2(arg): return arg
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
请注意,我们还通过将函数体语句放在与定义语句相同的行上,节省了一行。`lambda`函数结构正是这两种结构中的后一种,即一个返回某些东西的单语句函数,区别在于“return”关键字是隐含的,并不出现在构造中。现在我们知道了`lambda`函数是如何工作的(与一个单语句函数相同),让我们以`lambda`的形式构造 *simple2* 函数。为此,我们简单地使用`lambda`构造——如果我们将我们的`lambda`函数称为最简单的*,它将是这样的:*
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
simplest = lambda arg: arg
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
就是这样!现在我们有了*最简单的*和*简单的 2* ,它们的行为方式完全相同,但是前者我们用的术语要少得多;然而,从技术上讲,我们只保存了两个角色,这有什么大不了的?
|
|||
|
|
|
|||
|
|
如果我们仔细查看`lambda`语句,我们会发现它实际上是一个语句,即*返回*一个函数(这就是为什么我们将它赋给一个变量),这就是`lambda`构造的真正力量所在,所以让我们来看一个利用这种力量的例子。
|
|||
|
|
|
|||
|
|
假设我们有一个三元组列表,如下所示:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
tups = [
|
|||
|
|
|
|||
|
|
(1, 3, -2),
|
|||
|
|
|
|||
|
|
(3, 2, 1),
|
|||
|
|
|
|||
|
|
(-1, 0, 4),
|
|||
|
|
|
|||
|
|
(0, -1, 3),
|
|||
|
|
|
|||
|
|
(-2, 6, -5)
|
|||
|
|
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果我们想要 tups 的排序版本,我们只需将它交给内置的`sorted`方法:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
>>> sorted(tups)
|
|||
|
|
|
|||
|
|
[(-2, 6, -5), (-1, 0, 4), (0, -1, 3), (1, 3, -2), (3, 2, 1)]
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果我们*只有*想要按照每个元组中的**第一个**值排序,这没问题,但是如果我们想要按照第二个或第三个值排序呢?知道了内置的`sorted`方法是如何工作的,我们可以使用 *key* 参数来定义一个将返回所需值的函数(参见[如何通过键或值对 Python 字典进行排序](https://www.pythoncentral.io/how-to-sort-python-dictionaries-by-key-or-value/)以了解关于`sorted`的一些背景知识)。下面是它如何查找每个元组中第二个值的排序:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
>>> def sortkey(tup):
|
|||
|
|
|
|||
|
|
... return tup[1]
|
|||
|
|
|
|||
|
|
>>> sorted(tups, key=sortkey)
|
|||
|
|
|
|||
|
|
[(0, -1, 3), (-1, 0, 4), (3, 2, 1), (1, 3, -2), (-2, 6, -5)]
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这工作得很完美,但是我们已经用光了额外的空间/行(如果在脚本文件中的话),和额外的内存用于一个只帮助排序我们的列表的单语句函数。如果使用不同的语言,我们可能别无选择,只能这样做(或者更糟),但幸运的是我们有`lambda`函数构造:-)。有了它,我们可以用更简单的形式定义相同的函数:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
# Returns a function
|
|||
|
|
|
|||
|
|
>>> lambda tup: tup[1]
|
|||
|
|
|
|||
|
|
<function <lambda> at 0x02BD1230>
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
在*最简单的*的情况下,我们将由`lambda`构造/语句返回的 lambda 函数赋值,但是 lambda 构造的强大之处在于我们*不需要*这么做。相反,我们可以直接使用`sorted`中的语句作为键:
|
|||
|
|
|
|||
|
|
```py
|
|||
|
|
|
|||
|
|
>>> sorted(tups, key=lambda tup: tup[1])
|
|||
|
|
|
|||
|
|
[(0, -1, 3), (-1, 0, 4), (3, 2, 1), (1, 3, -2), (-2, 6, -5)]
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
它的工作方式与`sortkey`相同,但是使用这种形式,过程更简单,节省了行和内存!
|
|||
|
|
|
|||
|
|
这就是`lambda`函数及其构造的强大之处,但最棒的是它也适用于你的脚本中需要这样一个函数的任何部分。这包括内置的排序/迭代函数(如`sorted`、`map`和`filter`)、类方法如`re.sub`(将`repl`参数作为函数)、实例方法(如`list.sort`)、`Tkinter`小部件的回调函数等。因此,不要犹豫,将`lambda`功能投入使用,探索它们能够做的一切!*
|