0

私がこのようなクラスを書いた最初の人だとは想像できません:

class RestartableGenerator:
    def __init__(self, g):
        self.g = g
    def __iter__(self):
        return self.g().__iter__()

if __name__=='__main__':
    def gen():
        print 'Generating'
        for i in range(5):
            yield i
    i = RestartableGenerator(gen)
    print 'Using'
    print list(i)
    print list(i)

テストにより、次の出力が生成されます。

Using
Generating
[0, 1, 2, 3, 4]
Generating
[0, 1, 2, 3, 4]

しかし、標準ライブラリには見つかりませんでした。私は itertools と functools を見ました。

本当にないのでしょうか?もしそうなら、どこですか?

シーケンスを複数回評価したい場合は、リストに保存する方がよいため、不要だと考えられましたか?

編集1:私のユースケースは、メモリ消費の理由から、シーケンスがリストではなくジェネレータであることを消費者に透過的にしたいということです。

編集 2: 標準ライブラリにそのようなクラスがない場合、どの名前が適切だと思いますか? 括弧リムーバー? MultipleTimesIterable? 他に何か?なんで?

4

2 に答える 2

2

少し単純化できます:

class RestartableGenerator:
    def __init__(self, g):
        self.g = g
    def __iter__(self):
        return self.g()

を呼び出すgen()と、ジェネレータ オブジェクトが返されます。ジェネレーター オブジェクトにはnextメソッドがあり、これは__iter__返さなければならない種類のオブジェクトです。

RestartableGeneratorただし、それgen自体ができないことは何もしないため、 は必要ありません。genクラス属性を保持する代わりに、genそれ自体を保持します。

def gen():
    print 'Generating'
    for i in range(5):
        yield i

print 'Using'
print list(gen())
print list(gen())
于 2013-08-22T20:50:46.033 に答える
2

これは、シーケンスの最初に戻るという意味で、正確には再開可能ではありません。各__iter__呼び出しは、ジェネレーター コードを再実行する新しいジェネレーターを作成し、副作用を再実行して異なる結果を生成する可能性があります。生成されたシーケンスに対して独立した反復子が必要なlist場合itertools.teeは、それが目的です。それ以外の場合は、ジェネレーター関数を明示的に再度呼び出す方が明確であるため、これはあまり役に立ちません。明示性が低く、バグが発生しやすいコードを犠牲にして、括弧のペアを節約します。

遅延シーケンス型が必要な場合、反復処理によってその場で要素が生成されますが、反復処理は繰り返し可能であり、その__iter__メソッドをジェネレーターとして定義する必要があります。

class Primes(object):
    def __iter__(self):
        for i in itertools.count():
            if is_prime(i):
                yield i

これは「再起動可能なジェネレーター」ではありませんが、必要なように聞こえます。

于 2013-08-22T20:54:57.953 に答える