Python-字典中的函数赋值不正确
我试图通过使用字典来包含和索引与某些计算相关的函数来简化我的一些代码。我遇到了一个问题,字典中的函数变得混乱,行为不可预测 这说明了我的问题Python-字典中的函数赋值不正确,python,dictionary,lambda,Python,Dictionary,Lambda,我试图通过使用字典来包含和索引与某些计算相关的函数来简化我的一些代码。我遇到了一个问题,字典中的函数变得混乱,行为不可预测 这说明了我的问题 def y_at_x_first(x): return x * 1.0 def y_at_x_second(x): return x * 2.0 things = { 'first': { 'y_at_x': lambda x: y_at_x_first(x) }, 'second': {
def y_at_x_first(x):
return x * 1.0
def y_at_x_second(x):
return x * 2.0
things = {
'first': {
'y_at_x': lambda x: y_at_x_first(x)
},
'second': {
'y_at_x': lambda x: y_at_x_second(x)
},
}
for thing in things:
# Add a new function that makes use of the first
things[thing]['y2_at_x'] = lambda x: things[thing]['y_at_x'](x)
numbers = list(range(5))
print('first',
list(map(things['first']['y_at_x'], numbers)),
' = ',
list(map(things['first']['y2_at_x'], numbers)))
print('second',
list(map(things['second']['y_at_x'], numbers)),
' = ',
list(map(things['second']['y2_at_x'], numbers)))
我希望它能打印:
first [0.0, 1.0, 2.0, 3.0, 4.0] = [0.0, 1.0, 2.0, 3.0, 4.0]
second [0.0, 2.0, 4.0, 6.0, 8.0] = [0.0, 2.0, 4.0, 6.0, 8.0]
但它实际打印的内容是在以下两者之间的随机选择:
first [0.0, 1.0, 2.0, 3.0, 4.0] = [0.0, 2.0, 4.0, 6.0, 8.0]
second [0.0, 2.0, 4.0, 6.0, 8.0] = [0.0, 2.0, 4.0, 6.0, 8.0]
及
这实际上是一个随机选择,多次运行代码,代码会发生变化(我假设这与字典没有排序有关,所以随机性来自于此)。
我认为这一定是我的引用的问题,所以我尝试使用copy.deepcopy()
来包围所有函数引用,但问题仍然存在
非常感谢您的帮助。
我知道我正在尝试实现的其他方法,但我想知道这是我的理解还是Python的问题。
有趣的是,Python3的结果是随机的;在Python2中,结果始终是第二个选项(4.0作为元素4)。问题在于以下代码:
for thing in things:
# Add a new function that makes use of the first
things[thing]['y2_at_x'] = lambda x: things[thing]['y_at_x'](x)
您正在lambda函数中使用thing
,但是Python不会在lambda函数中“存储”该值,以备以后使用。例如,如果我将thing
更改为其他内容,则在调用函数时,它会将该值用于thing
:
>>> thing = 'foo'
>>> things['first']['y2_at_x'](3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in <lambda>
KeyError: 'foo'
通过访问循环中的函数对象,可以清楚地知道您使用的是什么对象,然后可以在lambda函数中调用它
for thing in things:
exec("things[thing]['y2_at_x'] = lambda x: things['"+thing+"']['y_at_x'](x)")
你所看到的随机性确实与以下事实有关,即字典是无序的,因此不知道是第一个
还是第二个
。正如Semeon所说:
您在lambda函数中使用了一些东西,但Python不会“存储”
此值位于lambda函数中,供以后使用
所以我需要一种在lambda函数中设置值的方法。
通过使用exec()
函数包装赋值,我可以让Python在lambda函数中“键入”正确的字符串
for thing in things:
exec("things[thing]['y2_at_x'] = lambda x: things['"+thing+"']['y_at_x'](x)")
这解决了问题,但我觉得使用exec语句并不是最优雅的解决方案。如果有人有更好的解决方案,我很乐意听到。请注意,
'y_at_x':lambda x:y_at_x_first(x)
可以比'y_at_x':y_at_x_first
更有效地完成。是的,谢谢。这个例子大大简化了,实际上我分配的函数是许多其他东西的组合。谢谢Simeon。那么,我如何在lambda定义中设置“thing”,使其始终指向正确的“thing”?我尝试了您设置f=things[thing]['y_at_x']
的示例,但仍然得到了相同的结果。
for thing in things:
exec("things[thing]['y2_at_x'] = lambda x: things['"+thing+"']['y_at_x'](x)")