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