<< >>

diveintopython.org |

Python for experienced programmers

## 2.8. 使用 `lambda` 函数

Python支持一种有趣的语法，它允许你快速定义单行的最小函数。这些叫做 `lambda` 的函数是从Lisp中借用来的，可以被用在任何需要函数的地方。

出于历史的原因，`lambda` 函数的语法与通常的函数有些细微的不同。

例 2.20. `lambda` 函数介绍

    >>> def f(x):
    ...     return x*2
    ...
    >>> f(3)
    6
    >>> g = lambda x: x*2
    >>> g(3)
    6
    >>> (lambda x: x*2)(3)
    6

| 这是一个通常的函数声明，尽管以前你可能没有看到过定义在交互式窗口中的函数。这个 ... 说明它是一个多行的交互语句。只要在第一行的后面敲入回车，Python IDE会让你接着输入命令。
| 这是一个 `lambda` 函数，它完成同上面普通函数相同的事情。注意这里的简短的语法；没有小括号， `return` 是默认的，并且函数没有名字，只有将它赋值给变量的变量名。
| 你甚至可以不将 `lambda` 函数赋值给一个变量而使用它。这不是举世无双的东西，它只是展示了 lambda 函数只是一个内联函数。

总之， `lambda` 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。 `lambda` 函数不能包含命令，它们所包含的表达式不能超过一个。不要试图向 `lambda` 函数中塞入太多的东西；如果你需要更复杂的东西，应该定义一个普通函数，然后想让它多长就多长。

`lambda` 函数是风格问题。不一定非要使用它们，任何能够使用它们的地方，都可以定义一个分离的普通的函数，用它来替换。我将它们用在需要封装特殊的，非重用的代码上，用许多小的一行函数不会弄乱我的代码。

例 2.21. 在 in `apihelper.py` 中的 `lambda` 函数

        processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

顺便这里有几件事情需要注意。首先，我们使用了 `and-or` 技巧的简单形式，没问题，因为一个 `lambda` 函数在一个布尔环境下总为真。(这并不意味着 `lambda` 函数不能返回假值。函数本身总是为真，它的返回值可以为任何值。)

第二，我们使用了 `split` 函数没带参数。你已经看到过它带1个或2个参数的使用，但是不带参数它按空白进行分割。

例 2.22. `split` 不带参数

    >>> s = "this   is\na\ttest"
    >>> print s
    this   is
    a	test
    >>> print s.split()
    ['this', 'is', 'a', 'test']
    >>> print " ".join(s.split())
    'this is a test'

| 这是一个多行字符串，通过转义字符的定义代替了三重引号。 `\n` 是一个回车； `\t` 是一个制表符。
| `split` 不带参数按空白进行分割。所以三个空格，一个回车，和一个制表符都是一样的。
| 你可以将空白统一化，通过分割一个字符串，然后用单个空格作为分隔符将其重新接起来。这就是 `help` 函数所做的，将多行文档字符串合并成单行。

那么 `help` 函数到底用这些 `lambda` 函数， `split` 函数，和 `and-or` 技巧做了什么呢？

例 2.23. 将函数赋给一个变量

        processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

`processFunc` 现在是一个函数，但它为哪一个函数要看 `collapse` 变量的值。如果 `collapse` 为真， ``processFunc`(string)` 将压缩空白；否则，``processFunc`(string)` 将返回未改变的参数。

在一个不很建壮的语言实现它，象VB，你将可能创建一个函数，它接收一个字符串和一个 `collapse` 参数，使用一个 `if` 语句来判断是否要压缩空白或不压缩，然后返回相应的值。这样效率低，因为函数将不得不处理每种可能性；每次你调用它，它将不得不在给出你所想要的东西之前，判断是否要压缩空白。在Python中，你可以将那种判断逻辑拿到函数外面，而定义一个裁减过的 `lambda` 函数来给出确切的(并且唯一)你想要的。这样做更有效率，更漂亮，并且更少导致那些令人讨厌的(哦，想到那些参数就头昏)的错误。

进一步阅读 |

- Python Knowledge Base 讨论了使用 `lambda` 来直接调用函数。
- Python Tutorial 演示了如何从一个 `lambda` 函数内部存取外部变量。(PEP 227 解释了为什么在Python 2.1中此技术不是必需的，因为Python 2.1支持嵌套作用域。)
- The Whole Python FAQ 有关于 令人模糊的使用 `lambda` 单行语句 的例子。

« and-or 技巧 | 全部放在一起 »