1

Here is what I tried:

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

What I expected to get from this line was a list of functions that each return the input values with some set of signs applied. For example, quadrant[1](x, y) -> (x, y), quadrant[2](x, y) -> (-x, y), and so on.

What I actually got is a list of four identical functions, all the last function that I put into the list. For example, quadrant[1](x, y) -> (-x, -y), quadrant[2](x, y) -> (-x, -y), and so on.

What am I misunderstanding here? Why does each new function added to the list replace all the previously added functions?

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))]

现在回答你的问题:

为什么添加到列表中的每个新功能都会替换之前添加的所有功能?

没有函数被替换,您的列表包含四个不同的函数,如您在此处看到的:

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 回答