2013-06-10 3 views
5

私は、外部関数が内部関数を返すクロージャ、または特にメモ化には言及していません。おそらくメモ帳を使って再帰関数を書こうと思っていた例がいくつかありました。外部関数の中にaa dictや他のデータ構造を初期化してから、 dictと外部関数の引数にアクセスします。私はこれを行うことはメモ化のためにかなり標準であることを読んだことがあるPythonでネストされた関数を使うのは良いですか?

recursive_foo_helper(arr, l, i, j, k, cache={}, result=[]) 

def foo(arr, l): 
    cache = {} 
    result = [] 

    def recursive_foo_helper(i, j, k): 
     # some code that depends on arr, l, i, j, k, cache, and result 

    for (x, y) in arr: 
     if recursive_foo_helper(x, y, k): 
     return result 
    return None 

の代わりに、ヘルパー関数は、いくつかの超ロング署名などで個別に宣言した、が、私はだった - ここで私が何を意味するかです再帰的なヘルパー関数のためだけに行うことができるかどうかについて合意があるかどうか不思議です。

+0

他の場所でこの関数を呼び出さない場合、なぜこれが悪いことになるのかわかりません。 – OptimusCrime

答えて

4

私は、リストから一致するものを見つけるために、ネストされた関数を使用します。

def get_exact(data, key, match): 
    def is_match(item): 
     if (key in item) and (item[key].lower() == match.lower()): 
      return item 
     return False 
    return [i for i in data if is_match(i)] 

プロジェクト内の他の呼び出しはis_match(アイテム)を使用する必要がないので、なぜ別にそれを宣言しますか?

しかし、私の例では、get_exact()の外側でis_match()を宣言すると、~0.04 secondsが10,000回の反復で高速に実行されます。

def is_match(item, key, match): 
    if (key in item) and (item[key].lower() == match.lower()): 
     return item 
    return False 

def get_exact(data, key, match): 
    return [i for i in data if is_match(i, key, match)] 
1

は、私はあなたがきれいであることを示唆としてクロージャを使用して言うが、あなたは参照を再バインドしたい場合は、本当にのpython3からnonlocalキーワードを必要とするだろう。変更可能なオブジェクトの場合、それらを変更することは明らかです。一方

、それはPython2

Oneのdefaultargハック/イディオムを参照するのが一般的です(多分のみ)ネストされた関数の欠点は、unittestのが困難だということです。

キャッシュが無制限に成長できないことを確認するために、あなたはまた、アイテムを削除する方法が必要です(例えば最低使用)

1

理由はたくさんあります。個人的には、名前空間をきれいに保つために入れ子関数を使用することがよくあります。これは、オブジェクトのメソッド内で特に便利です:

class Foo(object): 
    def bar(self): 
     def baz(val): 
      return val 
     return [ baz(i) for i in range(1,101) ] 

私はbarbaz外を宣言した場合、私はどちらかそれFooの方法にする必要がある、またはパッケージ全体に公開します。

2

私はたいていクロージャを使用しますが、私は時々ラッパーと呼ばれるものを提案していますが、私の個人的な経験ではうまくいきます。私は誰かにそのスタイルを避けるよう教えてもらえませんでした。あなたのコードが動作し、(私はそれがそうだと思う)読み込み可能な場合は、それを行ってください!

関連する問題