11

私の関数はジェネレーターのチェーンを作成します:

def bar(num):
    import itertools
    some_sequence = (x*1.5 for x in range(num))
    some_other_sequence = (x*2.6 for x in range(num))
    chained = itertools.chain(some_sequence, some_other_sequence)
    return chained

chained私の関数は時々逆の順序で戻る必要があります。概念的には、次のことができるようになりたいと考えています。

if num < 0:
    return reversed(chained)
return chained

不運にも:

>>> reversed(chained)
TypeError: argument to reversed() must be a sequence

私のオプションは何ですか?

これはいくつかのリアルタイム グラフィック レンダリング コードに含まれているため、複雑すぎたり遅くしたりしたくありません。

編集:私が最初にこの質問をしたとき、私はジェネレーターの可逆性について考えていませんでした。多くの人が指摘しているように、ジェネレーターを元に戻すことはできません。

実際、チェーンの平坦化された内容を逆にしたいのです。ジェネレーターの順序だけではありません。

応答に基づいて、itertools.chain を逆にするために使用できる単一の呼び出しはありません。したがって、ここでの唯一の解決策は、少なくとも逆の場合、おそらく両方の場合にリストを使用することだと思います。

4

7 に答える 7

12
if num < 0:
    lst = list(chained)
    lst.reverse()
    return lst
else:
    return chained

reversed()インデックスによって逆方向に反復するため、実際のシーケンスが必要であり、ジェネレーター (「次の」アイテムの概念しかない) では機能しません。

いずれにせよリバースするにはジェネレーター全体をアンロールする必要があるため、最も効率的な方法は、それをリストに読み取り、メソッドを使用してその場でリストをリバースする.reverse()ことです。

于 2011-02-15T20:13:02.413 に答える
11

定義上、ジェネレーターを逆にすることはできません。ジェネレーターのインターフェースは、前方反復のみをサポートするコンテナーであるイテレーターです。イテレータを逆にしたいときは、最初にすべてのアイテムを収集し、その後それらを逆にする必要があります。

代わりにリストを使用するか、シーケンスを最初から逆方向に生成してください。

于 2011-02-15T20:20:10.103 に答える
4

itertools.chain を実装する必要があります__reversed__()(これが最適です) または__len__()__getitem__()

そうではなく、内部シーケンスにアクセスする方法さえないため、シーケンス全体を展開して元に戻すことができるようにする必要があります。

reversed(list(CHAIN_INSTANCE))

すべてのシーケンスが可逆である場合に chain が使用可能になるとよいのです__reversed__()が、現在はそうではありません。おそらく、チェーンの独自のバージョンを作成できます

于 2011-02-15T22:40:54.857 に答える
1
def reversed2(iter):
    return reversed(list(iter))
于 2011-06-10T04:55:01.077 に答える
0

reversedlenインデックス作成をサポートするオブジェクトでのみ機能します。それらをラップする前に、最初にジェネレーターのすべての結果を生成する必要がありreversedます。

ただし、これは簡単に実行できます。

def bar(num):
    import itertools
    some_sequence = (x*1.5 for x in range(num, -1, -1))
    some_other_sequence = (x*2.6 for x in range(num, -1, -1))
    chained = itertools.chain(some_other_sequence, some_sequence)
    return chained
于 2011-02-15T20:11:11.653 に答える
0

これは実際のアプリで機能しますか?

def bar(num):
    import itertools
    some_sequence = (x*1.5 for x in range(num))
    some_other_sequence = (x*2.6 for x in range(num))
    list_of_chains = [some_sequence, some_other_sequence]
    if num < 0:
        list_of_chains.reverse()
    chained = itertools.chain(*list_of_chains)
    return chained
于 2011-02-15T20:11:41.047 に答える
0

チェーンされたオブジェクトには などの無限のシーケンスが含まれている可能性があるため、理論的にはできませんitertools.count(...)

ジェネレーター/シーケンスを逆にするreversed(iterable)か、該当する場合は各シーケンスを使用してから、それらを最後から最初にチェーンする必要があります。もちろん、これはユースケースに大きく依存します。

于 2011-02-15T20:21:25.370 に答える