無限の要素を生成できる単純なジェネレーター式はありますか?
これは純粋に理論的な質問です。ここで「実用的な」答えは必要ありません:)
たとえば、有限ジェネレーターを簡単に作成できます。
my_gen = (0 for i in xrange(42))
ただし、無限の名前を作成するには、名前空間を偽の関数で「汚染」する必要があります。
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
別のファイルで処理を行い、後でimport
- ingを実行してもカウントされません。
itertools.repeat
はまさにこれを行います。私はそれなしでワンライナーソリューションがあるかどうか興味があります。
_for x in iter(int, 1): pass
_
iter
=引数なしの呼び出し可能+センチネル値int()
は常に_0
_を返しますしたがって、iter(int, 1)
は無限イテレータです。この特定のテーマには明らかに膨大な数のバリエーションがあります(特にlambda
をミックスに追加すると)。特定の注記の1つの変形はiter(f, object())
です。センチネル値として最初に作成されたオブジェクトを使用すると、最初の引数として使用される呼び出し可能オブジェクトに関係なく、無限イテレータがほぼ保証されます。
itertools
は、3つの無限ジェネレーターを提供します。
count(start=0, step=1)
:0、1、2、3、4、...
cycle(p)
:p [0]、p [1]、...、p [-1]、p [0]、...
repeat(x, times=∞)
:x、x、x、x、...
標準ライブラリの他のものは知りません。
ワンライナーを求めたので:
__import__("itertools").count()
iter()のセンチネルとは常に異なる定数を返す呼び出し可能オブジェクトを反復処理できます
g1=iter(lambda:0,1)
OSは、無限ジェネレーターとして使用できるものを提供する場合があります。例えば、Linuxで
for i in (0 for x in open('/dev/urandom')):
print i
明らかにこれはそれほど効率的ではありません
for i in __import__('itertools').repeat(0)
print i
クラス/関数/ジェネレーターとして定義された別の無限イテレーターを内部的に使用しないものはありません(-expression、yield
を持つ関数ではありません)。ジェネレーター式は常にイテレータから描画し、アイテムのフィルタリングとマッピングのみを行います。 map
とfilter
のみで有限アイテムから無限アイテムに移動することはできません。while
(または終了しないfor
が必要です。これは、for
と有限イテレータのみを使用することはできません。
雑学: PEP 3142 は表面的には似ていますが、よく調べてみると、for
節が必要なようです(したがって、(0 while True)
for you)、つまり、itertools.takewhile
。
非常にくてクレイジー(ただし非常に面白い)ですが、いくつかのトリックを使用して(必要に応じてネームスペースを「汚染」せずに)式から独自のイテレーターを作成できます。
{ 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,), {}))() }
たとえば、次のようなデコレータを使用できます。
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
これらのい()
を取り除くことで、さらに改善できると思います。ただし、作成できるシーケンスの複雑さによって異なります。一般的に、関数を使用してシーケンスを表現できる場合、ジェネレーターのすべての複雑さと構文糖は、デコレーターまたはデコレーターのような関数内に隠すことができます。