閉鎖から抜け出す必要があります。
quadrant = [ (lambda sign: lambda x, y: (sign[0] * x, sign[1] * y) ) (sign)
for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
または、Blender が指摘したように、名前付き関数を使用して:
def wrapper (sign):
def makeQuadrant (x, y):
return (sign [0] * x, sign [1] * y)
return makeQuadrant
quadrant = [wrapper (sign) for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
または、chepnerが指摘したように、デフォルトの名前付きパラメーターを使用します。
quadrant = [lambda x, y, sign = sign: (sign[0] * x, sign[1] * y)
for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
そして今、あなたの質問に答えるために:
リストに新しい関数が追加されるたびに、以前に追加されたすべての関数が置き換えられるのはなぜですか?
関数は置き換えられません。リストには、次のように 4 つの異なる関数が含まれています。
quadrant = [lambda x, y: (sign[0] * x, sign[1] * y, id (sign) )
for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
for q in quadrant:
print (id (q) )
何が起こるかとsign
いうと、関数が呼び出されたときに の値が検索されます。の現在の値はsign
、リスト内包表記中に割り当てられた最後の値です。これは(-1, -1)
です。ここで見ることができます:
quadrant = [lambda x, y: (sign[0] * x, sign[1] * y, id (sign) )
for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
for q in quadrant:
print (q (2, 3) )
さらに読むために、「スコープ」と「クロージャー」を少し調べたいと思うかもしれません。
あなたの例は基本的にこれに要約されます:
fs = [lambda: x for x in range (10) ]
for f in fs: print (f () )