2

我正在阅读 Mark Pilgrim 的 Dive into Python 3。他给出了名词复数形式的“必杀技”代码。我的问题是:第 30 行和第 31 行的代码是否必要?没有它们,该程序似乎运行良好。添加它们有什么好处?谢谢

    import re
    def build_match_and_apply_functions(pattern, search, replace):
        def matches_rule(word):
            return re.search(pattern, word)
        def apply_rule(word):
            return re.sub(search, replace, word)
        return (matches_rule, apply_rule)

def plural(noun):
    for matches_rule, apply_rule in rules:
        if matches_rule(noun):
            return apply_rule(noun)
    raise ValueError('no matching rule for {0}'.format(noun))

class LazyRules:
    rules_filename = 'plural6-rules.txt'
    def __init__(self):
        self.pattern_file = open(self.rules_filename, encoding='utf-8')
        self.cache = []

    def __iter__(self):
        self.cache_index = 0
        return self

    def __next__(self):
        self.cache_index += 1
        if len(self.cache) >= self.cache_index:
            return self.cache[self.cache_index - 1]

##Line 30:        if self.pattern_file.closed:
##Line 31:            raise StopIteration

        line = self.pattern_file.readline()
        if not line:
            self.pattern_file.close()
            raise StopIteration

        pattern, search, replace = line.split(None, 3)
        funcs = build_match_and_apply_functions(pattern, search, replace)
        self.cache.append(funcs)
        return funcs

rules = LazyRules()
nouns=['fox', 'horse', 'cheetah','ad', 'quay', 'vacancy']
for noun in nouns:
    print (noun)
    print(plural(noun)+'\n')

## plural6-rules.txt:
##[sxz]$ $ es
##[^aeioudgkprt]h$ $ es
##[^aeiou]y$ y$ ies
##$   $   s
4

2 回答 2

1

是的,正如书中解释的那样,这些行是必要的(见注 2)。

在之前的迭代中,模式文件可能已经关闭。

通过 raise StopIteration,一个 for 循环将优雅地退出(见注 5

如果你不这样做raise StopIteration,下一行将尝试从一个关闭的文件中读取。

line = self.pattern_file.readline()

这会导致ValueError.

要演示这些行何时运行,请尝试删除plural6-rules.txt文件的最后一行(匹配所有内容),然后键入以下内容。

>>> from plural6 import plural
>>> plural("fox") # matches the first rule
'foxes'
>>> plural("foo") # does not match any rules. file is closed.
>>> plural("foo") # We have removed the check, we will try to read from a closed file
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "plural6.py", line 50, in plural
    for matches_rule, apply_rule in rules:
  File "plural6.py", line 36, in __next__
    line = self.pattern_file.readline()
ValueError: I/O operation on closed file.
于 2012-05-30T23:16:05.723 回答
-1

它们不是必需的,因为代码只向下几行(当readline()返回一个空字符串时关闭文件,表示文件结束)然后引发StopIteration。没有文件会从先前的迭代中关闭的情况。好吧,我想如果你next()在文件关闭后继续调用它,但你使用的代码并没有这样做。

一般来说,该代码很糟糕。这是那本书的典型吗?如果是这样,请将其扔掉并尝试另一个。

于 2012-05-30T23:39:48.897 回答