17.4. plural.py,阶段 3

为每个匹配和应用规则定义单独的命名函数实际上是没有必要的。您永远不会直接调用它们;您在 rules 列表中定义它们并通过那里调用它们。让我们通过匿名化这些函数来简化规则定义。

示例 17.8. plural3.py


import re

rules = \
  (
    (
     lambda word: re.search('[sxz]$', word),
     lambda word: re.sub('$', 'es', word)
    ),
    (
     lambda word: re.search('[^aeioudgkprt]h$', word),
     lambda word: re.sub('$', 'es', word)
    ),
    (
     lambda word: re.search('[^aeiou]y$', word),
     lambda word: re.sub('y$', 'ies', word)
    ),
    (
     lambda word: re.search('$', word),
     lambda word: re.sub('$', 's', word)
    )
   )                                           1

def plural(noun):                             
    for matchesRule, applyRule in rules:       2
        if matchesRule(noun):                 
            return applyRule(noun)            
1 这与您在阶段 2 中定义的规则集相同。唯一的区别是,您没有定义像 match_sxzapply_sxz 这样的命名函数,而是使用 lambda 函数将这些函数定义直接“内联”到 rules 列表本身中。
2 请注意,plural 函数根本没有改变。它遍历一组规则函数,检查第一个规则,如果它返回真值,则调用第二个规则并返回值。与上面一样,逐字逐句。唯一的区别是规则函数是使用 lambda 函数内联、匿名定义的。但是 plural 函数并不关心它们是如何定义的;它只是获取规则列表并盲目地处理它们。

现在要添加新规则,您需要做的就是在 rules 列表本身中直接定义函数:一个匹配规则和一个应用规则。但是像这样内联定义规则函数可以很清楚地看出,您在这里有一些不必要的重复。您有四对函数,它们都遵循相同的模式。匹配函数是对 re.search 的单个调用,应用函数是对 re.sub 的单个调用。让我们排除这些相似之处。