15

特に、外側の関数が内側の関数を返すクロージャーやメモ化について言及しているのではありません。おそらくメモ化を使用して、再帰関数を書きたいと思ったいくつかのインスタンスがありました。外部関数で辞書またはその他のデータ構造を初期化し、再帰ヘルパー関数に書き込む方がはるかに簡単に思えました。外部関数のdictと引数にアクセスします。これが私が言いたいことです -

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

次のような非常に長いシグネチャを使用してヘルパー関数を個別に宣言する代わりに、

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

これを行うことはメモ化にとってかなり標準的であることを読んだことがありますが、再帰的なヘルパー関数のためだけに行ってもよいかどうかについてのコンセンサスがあるかどうかに興味がありました.

4

4 に答える 4

9

多くの正当な理由があります。個人的には、ネストされた関数を使用して名前空間をクリーンに保つことがよくあります。これは、オブジェクト メソッド内で特に役立ちます。

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

bazの外部で宣言する場合はbar、 のメソッドにするかFoo、パッケージ全体に公開する必要があります。

于 2013-06-10T22:47:23.097 に答える
4

私は通常クロージャーを使用しますが、あなたが提案する他の方法 (私が時々ラッパーと呼ぶもの) も非常に便利で、私の個人的な経験では問題なく動作します。そのスタイルを避けるように誰かに言われたことは一度もありません。あなたのコードが機能し、読み取り可能である場合 (私はそうだと思います)、それを試してください!

于 2013-06-10T23:12:09.483 に答える
1

あなたが提案するようにクロージャーを使用する方がクリーンだと思いますが、nonlocal参照を再バインドする場合は、Python3 のキーワードが本当に必要です。変更可能なオブジェクトの場合、それらを変更することは明らかに問題ありません。

それまでの間、Python2 で defaultarg のハック/イディオムがよく見られます。

ネストされた関数の 1 つの (おそらく唯一の) 欠点は、単体テストが難しいことです。

キャッシュが際限なく大きくならないようにするには、アイテムを削除する方法も必要です (例: 使用頻度が最も低いもの)。

于 2013-06-10T22:36:38.903 に答える