9

ファイルを開くイテレータクラスを作成しました__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()  
4

2 に答える 2

16

全体を書くためのより良い方法は、オープニングとイテレーションを1か所に保持することです。

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 = ....
于 2013-02-10T13:15:11.327 に答える
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()StopIterationexcept StopIteration:

これはケースのみを処理します。StopIteration他の状況(イテレーターを使い果たしていない)を処理したい場合は、その状況を個別に処理する必要があります。クラスをコンテキストマネージャー にすることも、それを助けることができます。イテレータのユーザーは、オブジェクトを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
于 2013-02-10T13:01:59.407 に答える