我正在阅读Mark Pilgrim's Dive in Python 3.他给出了用于复制名词的“必杀技”代码。我的问题是:第30行和第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
答案 0 :(得分:1)
是的,这些行是必要的,如book explains(见注释2)。
在上一次迭代中,模式文件可能已经关闭。
通过提升StopIteration
,for循环将正常退出(请参阅note 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.
答案 1 :(得分:-1)
它们不是必需的,因为代码只需几行(当readline()
返回空字符串时关闭文件,指示文件的结尾)然后引发StopIteration
。在任何情况下都不会从之前的迭代中关闭文件。好吧,我想如果你在文件关闭后继续调用next()
,但你使用的代码不会这样做。
一般来说,这段代码很糟糕。这本书很典型吗?如果是这样,扔掉它再尝试另一个。