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)
         )                                     1

def plural(noun):                             
    for matchesRule, applyRule in rules:       2
        if matchesRule(noun):                  3
            return applyRule(noun)             4
1 这个版本看起来更加复杂 (至少是长了),但做的工作没有变化:试图顺序匹配四种不同规则,并在匹配时应用恰当的正则表达式。 不同之处在于,每个独立的匹配和应用规则都在自己的函数中定义,并且这些函数列于 rules 变量这个元组的元组之中。
2 使用一个 for 循环,你可以根据 rules 元组一次性进行匹配和应用规则两项工作(一个匹配和一个应用)。 for 循环第一轮中,matchesRule 将使用 match_sxzapplyRule 将使用 apply_sxz; 在第二轮中(假设真走到了这么远), matchesRule 将被赋予 match_happlyRule 将被赋予 apply_h
3 记住 Python 中的一切都是对象,包括函数。rules 包含函数:不是指函数名,而是指函数本身。 当他们被赋予给 for 循环中, matchesRuleapplyRule 就成了你可以调用的真正函数。 因此,在 for 循环第一轮中,就相当于调用 matches_sxz(noun)
4 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_fooapply_foo,然后更新 rules 列表指定在什么相对位置调用这个新匹配和新规则应用。

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