web-dev-qa-db-ja.com

無限ジェネレーターの式はありますか?

無限の要素を生成できる単純なジェネレーター式はありますか?

これは純粋に理論的な質問です。ここで「実用的な」答えは必要ありません:)


たとえば、有限ジェネレーターを簡単に作成できます。

my_gen = (0 for i in xrange(42))

ただし、無限の名前を作成するには、名前空間を偽の関数で「汚染」する必要があります。

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

別のファイルで処理を行い、後でimport- ingを実行してもカウントされません。


itertools.repeatはまさにこれを行います。私はそれなしでワンライナーソリューションがあるかどうか興味があります。

102
hugomg
_for x in iter(int, 1): pass
_
  • 2つの引数iter =引数なしの呼び出し可能+センチネル値
  • int()は常に_0_を返します

したがって、iter(int, 1)は無限イテレータです。この特定のテーマには明らかに膨大な数のバリエーションがあります(特にlambdaをミックスに追加すると)。特定の注記の1つの変形はiter(f, object())です。センチネル値として最初に作成されたオブジェクトを使用すると、最初の引数として使用される呼び出し可能オブジェクトに関係なく、無限イテレータがほぼ保証されます。

118
ncoghlan

itertools は、3つの無限ジェネレーターを提供します。

標準ライブラリの他のものは知りません。


ワンライナーを求めたので:

__import__("itertools").count()
178
Katriel

iter()のセンチネルとは常に異なる定数を返す呼び出し可能オブジェクトを反復処理できます

g1=iter(lambda:0,1)
16
user237419

OSは、無限ジェネレーターとして使用できるものを提供する場合があります。例えば、Linuxで

for i in (0 for x in open('/dev/urandom')):
    print i

明らかにこれはそれほど効率的ではありません

for i in __import__('itertools').repeat(0)
    print i
6
John La Rooy

クラス/関数/ジェネレーターとして定義された別の無限イテレーターを内部的に使用しないものはありません(-expression、yieldを持つ関数ではありません)。ジェネレーター式は常にイテレータから描画し、アイテムのフィルタリングとマッピングのみを行います。 mapfilterのみで有限アイテムから無限アイテムに移動することはできません。while(または終了しないforが必要です。これは、forと有限イテレータのみを使用することはできません。

雑学: PEP 3142 は表面的には似ていますが、よく調べてみると、for節が必要なようです(したがって、(0 while True) for you)、つまり、itertools.takewhile

5
user395760

非常にくてクレイジー(ただし非常に面白い)ですが、いくつかのトリックを使用して(必要に応じてネームスペースを「汚染」せずに)式から独自のイテレーターを作成できます。

{ print("Hello world") for _ in
    (lambda o: setattr(o, '__iter__', lambda x:x)
            or setattr(o, '__next__', lambda x:True)
            or o)
    (type("EvilIterator", (object,), {}))() } 
4
Thomas Baruchel

たとえば、次のようなデコレータを使用できます。

def generator(first):
    def wrap(func):
        def seq():
            x = first
            while True:
                yield x
                x = func(x)
        return seq
    return wrap

使用法(1):

@generator(0)
def blah(x):
    return x + 1

for i in blah():
    print i

使い方(2)

for i in generator(0)(lambda x: x + 1)():
    print i

これらのい()を取り除くことで、さらに改善できると思います。ただし、作成できるシーケンスの複雑さによって異なります。一般的に、関数を使用してシーケンスを表現できる場合、ジェネレーターのすべての複雑さと構文糖は、デコレーターまたはデコレーターのような関数内に隠すことができます。

2
julkiewicz