2017-08-26 7 views
1

例えばrandom_spelling_errorのような有用な変換関数があるとします。n回適用したいと思います。関数を独自の出力にn回再適用するPythonの方法?

私の一時的な解決策は、次のようになります。

def reapply(n, fn, arg): 
    for i in range(n): 
     arg = fn(arg) 
    return arg 


reapply(3, random_spelling_error, "This is not a test!") 

はこれを行うには、内蔵またはその他のより良い方法はありますか?

可変長argsまたはキーワードargsを処理する必要はありませんが、可能です。関数はスケールで呼び出されますが、nの値は小さくなり、引数と戻り値のサイズは小さくなります。

私たちは、このreduceを呼び出すことができますが、その名前はもちろん、これを行うと、あまりにも多くのことができます機能のために採取した、ここではPython 3で削除されましたがGuido's argumentです:私の心の中でそう

、 reduce()の適用性は、 の連想演算子にかなり制限されており、他のすべてのケースでは、累積ループを明示的に書き出すほうがよいでしょう。

+0

をRのためのソリューションを参照してください。 https://stackoverflow.com/questions/29237136/relooping-a-function-over-its-own-output –

+3

私はあなたのループについて何か間違っているとか「un-pythonic」とは思わない。はい、おそらく3行ではなく1行で行えますが、何のために?それはすぐにそれが何をすべきか、それを非常にpythonic IMHOにすることが明らかです。 –

+1

@tobias_k私はそれが読める(そして効率的な)ものであることに同意します。私はただの大会があるのか​​、何かを重複しているのだろうかと思っています。 –

答えて

0

再帰のようないくつかは、常に明らかに 'より良い'

def reapply(n, fn, arg): 
    if n: 
     arg = reapply(n-1, fn, fn(arg)) 
    return arg 


reapply(1, lambda x: x**2, 2) 
Out[161]: 4 

reapply(2, lambda x: x**2, 2) 
Out[162]: 16 
+1

'n else arg'の場合には' return reapply(...) 'と短くすることができますが、IMHOの方がより明確ではありません(再帰制限?)。 –

1

reducefunctoolsモジュールを使ってPython 3でまだ利用可能ではありません。私は本当にこれ以上ニシキヘビのですが、ここであなたは1行でそれを達成することができる方法だということを知らない:

from functools import reduce 

def reapply(n, fn, arg): 
    return reduce(lambda x, _: fn(x), range(n), arg) 
+1

ありがとう、ループは読みやすく、インポートを保存するので、実際にはこれで選択しますが、これは 'reduce'でどのように処理されるのか不思議な人にとっては良い答えです。 –

0

は完全にカスタム関数を取り除く、あなたは混乱一つに2つの読める行を圧縮しようとしています関数呼び出し。

foo = reapply(3, random_spelling_error, foo) 

または1つの以上の行のシンプルforループ:

for _ in range(3): 
    foo = random_spelling_error(foo) 

更新:コメント

によると、あなたはあなたの方法、読みやすく、理解しやすくなりどちらだと思います

私が適用したい変換関数がたくさんあるとしましょう。

このような何かしようとしないのはなぜ:

modifiers = (random_spelling_error, another_function, apply_this_too) 
for modifier in modifiers: 
    for _ in range(3): 
     foo = modifier(foo) 

それとも、異なる機能のための繰り返しの異なる量が必要な場合は、タプルのリストを作成してみてください:

modifiers = [ 
    (random_spelling_error, 5), 
    (another_function, 3), 
    ... 
] 

for modifier, count in modifiers: 
    for _ in range(count): 
     foo = modifier(foo) 
+0

適用したい変換関数がたくさんあるとしましょう。 (存在します)関数が変数でなければならないという他の理由もあります。 –

+0

@ A.M.Bittlingmayer更新を参照してください。私はちょうど将来の開発者(将来的にも自分自身)がPythonのいくつかの行ですべて実行できるときに '再適用する 'ことを読むように強制するべきだとは思わない。 –

+0

そして、本当に*本当に*機能が必要な場合は、あなたの方法が最善の方法です。単純なままにしておきます。しかし、ここで関数を使うべきではないと思います。 –

関連する問題