8

iterate(f, x)値x、f(x)、f(f(x))、f(f(f(x)))など(たとえば、Clojureのiterate)を返すイテレーターを作成するPython関数が必要です。まず第一に、私は疑問に思っていました:これはすでに標準ライブラリのどこかに存在し、私はそれを見逃しているだけですか?もちろん、ジェネレーターを使用して実装するのは簡単です。

def iterate(f, x):
    while True:
        yield x
        x = f(x)

好奇心から:Pythonでこれを行うためのより機能的な方法はありますか?たとえば、いくつかのitertoolsまたはfunctoolsマジックを使用しますか?

Python 3.3では、これは機能します

def iterate(f, x):
    return accumulate(repeat(x), lambda acc, _ : f(acc))

しかし、私には虐待のように見えます。これをもっとうまくできますか?

4

2 に答える 2

6

itertoolsにはあなたが望むことをするものはないようですが、itertoolsは深い宝箱なので、何かを逃した可能性があります。

あなたのジェネレータコードは素晴らしく見えます。コードゴルフのばかげたゲームをプレイしていない限り、またはHaskellのスノッブを印象付けようとしているのでない限り、なぜそれを累積で書くのかわかりません。読みやすく、理解しやすく、保守しやすいように関数を記述します。過度に賢くする必要はありません。

于 2013-03-26T12:09:47.343 に答える
3

アナモルフィズム(または展開)を使用して、の定義を単純化し、iterate1つの開始値のみを使用できます。これは、非常によく知られている論文に基づいて、私がかつて使用した実装です。

def ana(build, predicate):
    def h(x):
        if predicate(x):
            return
        else:
            a, b = build(x)
            yield a
            for i in h(b):
                yield i
            # with newer syntax: 
            # yield from h(b)
    return h

iteratethenを使用した実装anaは次のようになります。

def iterate(f, x):
    return ana(lambda x: (x, f(x)), lambda _: False)(x)

ただし、itertoolsはありません...そして、これが最も読みやすいバリアントではないことに同意します。実際、それはかなり不可解です。


更新:より簡単なバージョンがありますが、これは非常に見栄えがします。ここから取ったものです:

def unfold(f, x):
    while True:
        w, x = f(x)
        yield w

そしてそれはあなたに与えます:

def iterate(f, x):
    return unfold(lambda y: (y, f(y)), x)
于 2013-03-27T17:36:56.057 に答える