我编写了一个迭代器类,在其__init__
中打开一个文件。
def __init__(self, path):
self.file = open(path, "r")
迭代完成后如何自动关闭该文件?
完整课程:
class Parse(object):
"""A generator that iterates through a CC-CEDICT formatted file, returning
a tuple of parsed results (Traditional, Simplified, Pinyin, English)"""
def __init__(self, path):
self.file = open(path, "r")
def __iter__(self):
return self
def __is_comment(self, line):
return line.startswith("#")
def next(self):
#This block ignores comments.
line = self.file.readline()
while line and self.__is_comment(line):
line = self.file.readline()
if line:
working = line.rstrip().split(" ")
trad, simp = working[0], working[1]
working = " ".join(working[2:]).split("]")
pinyin = working[0][1:]
english = working[1][1:]
return trad, simp, pinyin, english
else:
raise StopIteration()
答案 0 :(得分:11)
编写整个内容的更好方法是将开头和迭代保持在一个位置:
class Parse(object):
"""A generator that iterates through a CC-CEDICT formatted file, returning
a tuple of parsed results (Traditional, Simplified, Pinyin, English)"""
def __init__(self, path):
self.path = path
def __is_comment(self, line):
return line.startswith("#")
def __iter__(self):
with open(self.path) as f:
for line in f:
if self.__is_comment(line):
continue
working = line.rstrip().split(" ")
trad, simp = working[0], working[1]
working = " ".join(working[2:]).split("]")
pinyin = working[0][1:]
english = working[1][1:]
yield trad, simp, pinyin, english
这将等待打开文件,直到您真正需要它,并在完成后自动关闭它。它的代码也少了。
如果你真的想进入“发电机真棒!”心态:
def skip_comments(f):
for line in f:
if not.startswith('#'):
yield line
...
def __iter__(self):
with open(self.path) as f:
for line in skip_comments(f):
working = ....
答案 1 :(得分:1)
只要引发StopIteration
,就需要明确关闭它。在这种情况下,只需在自己举起.close()
时致电StopIteration
。
def next(self):
#This block ignores comments.
line = self.file.readline()
while line and self.__is_comment(line):
line = self.file.readline()
if line:
working = line.rstrip().split(" ")
trad, simp = working[0], working[1]
working = " ".join(working[2:]).split("]")
pinyin = working[0][1:]
english = working[1][1:]
return trad, simp, pinyin, english
else:
self.file.close()
raise StopIteration()
由于.next()
方法中没有其他代码可以触发StopIteration
这就足够了。
如果 在您自己的next()
内的另一个迭代器上使用.next()
,则必须使用StopIteration
处理程序捕获except StopIteration:
再加上例外。
此仅处理StopIteration
案例。如果你想处理其他情况(不要耗尽迭代器),你需要分别处理这种情况。让您的班级成为Context Manager 以及也可以提供帮助。然后迭代器的用户在迭代它之前在with
语句中使用该对象,并且当退出with
套件时,无论如何都可以关闭该文件。在这种情况下,您可能希望将迭代器标记为“已完成”:
_closed = False
def next(self):
if self._closed:
raise StopIteration
line = self.file.readline()
while line and self.__is_comment(line):
line = self.file.readline()
if line:
working = line.rstrip().split(" ")
trad, simp = working[0], working[1]
working = " ".join(working[2:]).split("]")
pinyin = working[0][1:]
english = working[1][1:]
return trad, simp, pinyin, english
else:
self.file.close()
self._closed = True
raise StopIteration()
def __enter__(self):
return self
def __exit__(self, type_, value, tb):
self.file.close() # multiple calls to .close() are fine
self._closed = True