17.3. plural.py, 第 2 阶段
Description: Python from novice to pro
Keywords: Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free

# 深入 Python :Dive Into Python 中文版 Python 从新手到专家 [Dip_5.4b_CPyUG_Release] | Find:

## 17.3. `plural.py`, 第 2 阶段

现在你将增加一个抽象过程。你从定义一个规则列表开始：如果这样，就做那个，否则判断下一规则。让我们暂时将程序一部分复杂化以便使另一部分简单化。

### 例 17.6. `plural2.py`

    import re

    def match_sxz(noun):
        return re.search('[sxz]$', noun)

    def apply_sxz(noun):
        return re.sub('$', 'es', noun)

    def match_h(noun):
        return re.search('[^aeioudgkprt]h$', noun)

    def apply_h(noun):
        return re.sub('$', 'es', noun)

    def match_y(noun):
        return re.search('[^aeiou]y$', noun)

    def apply_y(noun):
        return re.sub('y$', 'ies', noun)

    def match_default(noun):
        return 1

    def apply_default(noun):
        return noun + 's'

    rules = ((match_sxz, apply_sxz),
             (match_h, apply_h),
             (match_y, apply_y),
             (match_default, apply_default)
             )

    def plural(noun):
        for matchesRule, applyRule in rules:
            if matchesRule(noun):
                return applyRule(noun)

| 这个版本看起来更加复杂 (至少是长了)，但做的工作没有变化：试图顺序匹配四种不同规则，并在匹配时应用恰当的正则表达式。不同之处在于，每个独立的匹配和应用规则都在自己的函数中定义，并且这些函数列于 `rules` 变量这个元组的元组之中。
| 使用一个 `for` 循环，你可以根据 `rules` 元组一次性进行匹配和应用规则两项工作 (一个匹配和一个应用)。`for` 循环第一轮中，`matchesRule` 将使用 `match_sxz`，`applyRule` 将使用 `apply_sxz`；在第二轮中 (假设真走到了这么远)，`matchesRule` 将被赋予 `match_h`，`applyRule` 将被赋予 `apply_h`。
| 记住 Python 中的一切都是对象，包括函数。`rules` 包含函数；不是指函数名，而是指函数本身。当 `matchesRule` 和 `applyRule` 在 `for` 循环中被赋值后，它们就成了你可以调用的真正函数。因此，在 `for` 循环第一轮中，这就相当于调用 `matches_sxz(noun)`。
| 在 `for` 循环第一轮中，这就相当于调用 `apply_sxz(noun)`，等等。

这个抽象过程有些令人迷惑，试着剖析函数看看实际的等价内容。这个 `for` 循环相当于：

### 例 17.7. 剖析 `plural` 函数

    def plural(noun):
        if match_sxz(noun):
            return apply_sxz(noun)
        if match_h(noun):
            return apply_h(noun)
        if match_y(noun):
            return apply_y(noun)
        if match_default(noun):
            return apply_default(noun)

这里的好处在于 `plural` 函数现在被简化了。它以普通的方法反复使用其它地方定义的规则。获得一个匹配规则，匹配吗？调用并应用规则。规则可以在任意地方以任意方法定义，`plural` 函数对此并不关心。

现在，添加这个抽象过程值得吗？嗯……还不值。让我们看看如何向函数添加一个新的规则。啊哈，在先前的范例中，需要向 `plural` 函数添加一个 `if` 语句；在这个例子中，需要增加两个函数：`match_foo` 和 `apply_foo`，然后更新 `rules` 列表指定在什么相对位置调用这个新匹配和新规则应用。

这其实不过是步入下一节的一个基石。让我们继续。