Python - 字典中函数的错误分配

标签 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': {
        '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]

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, 1.0, 2.0, 3.0, 4.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'

您可以通过确保按预期使用 thing 来避免此问题(即,在 for 循环运行时它将具有适当的值):

for thing in things:
    # Add a new function that makes use of the first
    f = things[thing]['y_at_x']  # thing will have the value of the key here
    things[thing]['y2_at_x'] = lambda x: f(x)

通过访问循环中的函数对象,可以清楚地知道您正在使用什么对象,然后您可以在 lambda 函数中调用它。

您所看到的随机性确实与字典无序这一事实有关,因此不知道 firstsecond 是否先出现。

关于Python - 字典中函数的错误分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28490987/

相关文章:

Python+ flask : __init__() takes 2 positional arguments but 3 were given

python - 在 python 中使用 tkinter 时的新窗口

xcode - 无法将类型 'CLLocationDirection'(又名 'Double')的值转换为预期的参数类型 'Float'

java - 在 Java 中,什么类型表示函数或带有 3 个参数的 lambda 表达式?

python - 获取绑定(bind)到 Entry 小部件的 StringVar

python - 如何在从 manage.py 中定义的环境变量导入设置的项目上运行 django-pytest

javascript - 为什么当我返回数组而不是回调函数中的某些原语时,map 的工作方式有所不同?

iphone - 在iphone中从多个数组中添加数组中的对象

java - 在 lambda foreach 表达式 java 8 中获取索引

c# - 将条件 lambda 语句与列表上的 foreach 操作一起使用