2

重複の可能性:
関数の作成

>>> g=lambda x:x+1
>>> composition=lambda f,g:(lambda x:f(g(x)))
>>> f=g
>>> f=composition(f,g)
>>> f(9)
11
>>> f=composition(f,g)
>>> f=composition(f,g)
>>> f=composition(f,g)
>>> f(9)
14

function composition(f,g) を使用する代わりに、次のことを行いました

>>> f=g
>>> f=lambda x:f(g(x))
>>> f(8)
RuntimeError: maximum recursion depth exceeded

関数合成を対応するラムダ式に置き換えることを目指しました。f=composition(f,g) が再帰を生成しないのに f=lambda x:f(g(x)) が生成する理由について混乱しています。

4

2 に答える 2

2

最初のものについて:

を呼び出すとcomposition(f, g)、これらの変数の内容の周りにクロージャーが作成されます。f返されるラムダは、変数名とgそのローカル スコープを探しています。どちらもg最初の行で作成されたラムダへの参照になります。

2 つ目の場合:

2 番目のものでは、fが呼び出されると、f実際にはグローバル スコープである「ローカル」スコープで を検索し、自分自身を見つけるため、無限再帰が作成されます。

ここで重要なのは、ラムダが定義されたときではなく、実行f時に のルックアップが発生することです。

于 2012-09-14T21:25:15.613 に答える
1

これを書くとき:

f=lambda x:f(g(x))

結果のラムダは、「x のスコープ内にある g を呼び出した結果に対して、スコープ内にある f を呼び出す」ことを意味します。

これを書くとき:

f=composition(f, g)

結果として得られる関数は、「composition の最初のパラメーターが何であれ、composition の 2 番目のパラメーターがオンになっているものを呼び出した結果にあるものを呼び出す」ことを意味します。

これを理解するために詳細のどの部分を理解する必要があるかはわかりませんが、推測してみます。Python での引数の受け渡しは、名前ではなく常に参照渡しです。したがって、composition(f, g) を呼び出すときは、「変数」f ではなく、f が参照する関数オブジェクトを渡します。しかし、ラムダを定義すると、それはスコープ内で発生するだけなので、f 自体を参照しています。

補足として、これは、Guido がラムダ構文を使用する人々を好まない理由の一部です。次のようにコードを書き直すと、何が起こっているのかがより明確になります。

def g(x): return x+1
def composition(f,g):
  def composed(x): return f(g(x))
  return composed
f=g
f=composition(f,g)
于 2012-09-14T21:27:02.817 に答える