1

これが私が試したものです:

quadrant = [lambda x, y: (sign[0] * x, sign[1] * y)
    for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]

この行から得られると期待していたのは、それぞれが一連の符号を適用して入力値を返す関数のリストでした。たとえば、quadrant[1](x, y) -> (x, y)、quadrant[2](x, y) -> (-x, y) などです。

私が実際に取得したのは、4 つの同一の関数のリストであり、すべてリストに追加した最後の関数です。たとえば、quadrant[1](x, y) -> (-x, -y)、quadrant[2](x, y) -> (-x, -y) などです。

ここで私は何を誤解していますか?リストに新しい関数が追加されるたびに、以前に追加されたすべての関数が置き換えられるのはなぜですか?

4

1 に答える 1

1

閉鎖から抜け出す必要があります。

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 () )
于 2013-10-03T18:55:53.570 に答える