您在这里:首页 > 深入 Python > 动态函数 > plural.py,阶段 2 | << >> | ||||
深入 Python从 Python 新手到专家 |
现在我们要添加一个抽象层级。一开始,我们定义了一个规则列表:如果是这样,就那样做,否则就跳到下一条规则。让我们暂时把程序的一部分复杂化,以便简化另一部分。
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 包含实际的函数;不是函数的名称,而是实际的函数。当它们在 for 循环中被赋值时,matchesRule 和 applyRule 就是您可以调用的实际函数。所以在 for 循环的第一次迭代中,这相当于调用 matches_sxz(noun)。 |
![]() |
在 for 循环的第一次迭代中,这相当于调用 apply_sxz(noun),以此类推。 |
如果这种额外的抽象级别让您感到困惑,请尝试展开函数以查看等效性。这个 for 循环等效于以下内容
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 列表,以指定新的匹配和应用函数相对于其他规则应该在哪个位置调用。
这实际上只是下一节的垫脚石。让我们继续。
<< plural.py,阶段 1 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
plural.py,阶段 3 >> |