以下是我的尝试:
quadrant = [lambda x, y: (sign[0] * x, sign[1] * y)
for sign in ((1, -1), (1, 1), (-1, 1), (-1, -1))]
我期望从这一行获得的是一个函数列表,每个函数返回输入值并应用一些符号集。例如,象限[1](x,y) - > (x,y),象限[2](x,y) - > (-x,y),依此类推。
我实际得到的是一个包含四个相同函数的列表,这是我放入列表的所有最后一个函数。例如,象限[1](x,y) - > (-x,-y),象限[2](x,y) - > (-x,-y),等等。
我在这里误解了什么?为什么添加到列表中的每个新函数都会替换以前添加的所有函数?
答案 0 :(得分: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 () )