3 回答
TA贡献1770条经验 获得超3个赞
正如您所说,它创建了 CLOSURE,并且闭包在lambdaString的上部范围中使用指定变量,但技巧是所有 lambda 都使用对lambdaString的相同引用,并且因为每次它记住最后一个时都更改它。例如:
c = ['one', 'two']
res = []
for i in range(2):
for y in c:
def la(x):
print(x, y)
res.append(la)
for la in res:
la('Show: ')
# Show: two
# Show: two
# Show: two
# Show: two
你只需要另一个关闭来防止这种情况
c = ['one', 'two']
res = []
for i in range(2):
for y in c:
def closure_y(y):
def la(x):
print(x, y)
return la
res.append(closure_y(y))
for la in res:
la('Show: ')
# Show: one
# Show: two
# Show: one
# Show: two
完整代码可能是
specification = {
'labelOne': ['labelOne.one', 'labelOne.two', 'labelOne.three', 'labelOne.four', 'labelOne.five'],
'labelTwo': ['labelTwo.one', 'labelTwo.two', 'labelTwo.three', 'labelTwo.four', 'labelTwo.five'],
'labelThree': ['labelThree.one', 'labelThree.two', 'labelThree.three', 'labelThree.four', 'labelThree.five'],
'labelFour': ['labelFour.one', 'labelFour.two', 'labelFour.three', 'labelFour.four', 'labelFour.five'],
'labelFive': ['labelFive.one', 'labelFive.two', 'labelFive.three', 'labelFive.four', 'labelFive.five'],
}
lambdas = []
for label, labelStrings in specification.items():
for labelString in labelStrings:
lambdaString = f"""Label: \"{label}\" with labelString: \"{labelString}\""""
def clousure(lambdaString):
oneArgLambda = lambda someArg: print(someArg, lambdaString)
return oneArgLambda
lambdas.append(clousure(lambdaString))
for each in lambdas:
each('Show: ')
TA贡献1844条经验 获得超8个赞
您还有一些其他评论和答案来解释正在发生的事情,并且您的问题“有趣”是因为它迫使读者对代码和各种绑定问题感到困惑。
但是,如果我在审查过程中从同事那里看到了您的代码,我会要求重写 - 不是因为我会立即知道存在错误,而是因为它需要太多的头脑来思考是否来自周围的绑定(并改变) 范围将完全按照希望的方式运行。
相反,坚持在你的程序中实行更严格的纪律,从而减轻你的读者(大多数时候谁是你)的认知负担。具体来说,将函数创建移至真正隔离的范围,并将所有不同的输入传递给该函数创建者。这种方法是可靠的,因为它要么在第一次尝试时起作用,要么完全失败(如果您忽略将所有需要的参数传递给函数创建者)。
一种方法是:
# A function to create another function, with non-surprising argument binding.
# We expect nothing from the surrounding scope. All business can be done locally.
def get_func(label, x):
return lambda prefix: print(f'''{prefix} => {label}: {x}''')
# Some input data.
specification = {
label : [label + str(n) for n in range(3)]
for label in ('A', 'B', 'C')
}
# Use that data to create some functions.
funcs = [
get_func(label, x)
for label, xs in specification.items()
for x in xs
]
# Run 'em.
for f in funcs:
f('Show')
TA贡献1794条经验 获得超8个赞
这是一个替代方案
lambdas = []
for label, labelStrings in specification.items():
for labelString in labelStrings:
lambdaString = f"""Label: \"{label}\" with labelString: \"{labelString}\""""
oneArgLambda = lambda someArg, lambdaString: print(someArg, lambdaString)
lambdas.append((oneArgLambda, lambdaString))
for f, lambdaString in lambdas:
f('Show: ', lambdaString)
添加回答
举报