14

私は次のようなジェネレーター関数を持っています:

def mygenerator():
    next_value = compute_first_value() # Costly operation
    while next_value != terminating_value:
        yield next_value
        next_value = compute_next_value()

ジェネレーターが最初に使用されたときだけでなく、関数が呼び出されたらすぐに初期化ステップ(whileループの前)を実行したいと思います。これを行うための良い方法は何ですか?

ジェネレーターが別のスレッド(またはプロセス、またはマルチプロセッシングが使用するもの)で実行され、しばらくの間リターンを使用せず、初期化にいくらかコストがかかるため、これを実行したいので、それを希望します値を使用する準備をしている間に初期化を行います。

4

5 に答える 5

14
class mygenerator(object):
    def __init__(self):
        next_value = compute_first_value()
    def __iter__(self):
        return self
    def next(self):
        if next_value == terminating_value:
            raise StopIteration()
        return next_value
于 2011-04-20T00:56:24.593 に答える
14

似たようなものが必要でした。これが私が着陸したものです。ジェネレーター関数を内部にプッシュして、その呼び出しを返します。

def mygenerator():
    next_value = compute_first_value()

    def generator():
        while next_value != terminating_value:
            yield next_value
            next_value = compute_next(next_value)

    return generator()
于 2014-11-11T20:05:50.223 に答える
9

次を使用すると、「事前準備された」イテレータをかなり簡単に作成できますitertools.chain

from itertools import chain

def primed(iterable):
    """Preprimes an iterator so the first value is calculated immediately
       but not returned until the first iteration
    """
    itr = iter(iterable)
    try:
        first = next(itr)  # itr.next() in Python 2
    except StopIteration:
        return itr
    return chain([first], itr)

>>> def g():
...     for i in range(5):
...         print("Next called")
...         yield i
...
>>> x = primed(g())
Next called
>>> for i in x: print(i)
...
0
Next called
1
Next called
2
Next called
3
Next called
4
于 2011-04-20T02:58:38.513 に答える
5

最初のステートメントが完了した後、呼び出し元のコードでNoneを生成できると思います。

gen = mygenerator()
next(gen) # toss the None
do_something(gen)
于 2011-04-19T23:47:29.443 に答える
0

私のユースケースでは、@ ncoghlan回答の修正バージョンを使用しましたが、母関数を装飾するためにファクトリ関数でラップしました。

import collections, functools, itertools

def primed_generator(generating_function):
    @functools.wraps(generating_function)
    def get_first_right_away_wrapper(*args,**kw):
        "call the generator function, prime before returning"
        gen = generating_function(*args,**kw)
        assert isinstance(gen,collections.Iterator)
        first_value = next(gen)
        return itertools.chain((first_value,),gen)
    return get_first_right_away_wrapper

次に、関数を装飾します。

@primed_generator
def mygenerator():
    next_value = compute_first_value() # Costly operation
    while next_value != terminating_value:
        yield next_value
        next_value = compute_next_value()

最初の値はすぐに計算され、結果は透過的です。

于 2016-04-19T19:00:32.913 に答える