如何在Python中将lambda函数追加到列表中?

3

我正在尝试创建一个程序,它可以创建一个lambda函数列表,格式为y=mx+b,其中'm'和'b'是预定值。

我的总体目标是实现一个函数,该函数能够:

  • 拍照
  • 找到图像上的直线
  • 将其延伸到整个图像中,并以纯色显示

基本上,就像霍夫变换一样,如果您知道这是什么。

一旦我有了特定图像的直线,我可以创建一个lambda函数来表示线的斜率和起点。我无法将lambda函数附加到列表中,我遇到了问题。

我尝试过以下方法:

if __name__ == "__main__":
  nums = []
  for i in range(10):
    j = lambda x: x + i
    nums.append(j)
  for i in nums:
    print(i(1))

这是我遇到的错误:

Traceback (most recent call last):
  File "C:/Users/me/.PyCharmCE2018.3/config/scratches/scratch_3.py", line 7, in <module>
    print(i(1))
  File "C:/Users/me/.PyCharmCE2018.3/config/scratches/scratch_3.py", line 4, in <lambda>
    j = (lambda x: x + i)
TypeError: unsupported operand type(s) for +: 'int' and 'function'

请查看此处:http://book.pythontips.com/en/latest/lambdas.html - Mika72
所以我看了那个网站,基本上我尝试将“i”更改为“1”,这样就可以正常工作。为什么我不能使用“i”呢?对于我的真实项目,我需要在其中有一个可变的变量。 - Kei
请参阅 https://sopython.com/canon/30/why-do-my-lambda-functions-or-nested-functions-created-in-a-loop-all-use-the-las/。 - jonrsharpe
具体的错误是由于用于迭代函数的名称 i 将会在 lambda 表达式中进行查找。 - Karl Knechtel
5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
7
问题在于您创建的lambda表达式引用了活动栈帧中i的当前值。当您稍后再次使用i进行第二个for循环时,它将绑定到列表中的lambda表达式。当作i(1)调用时,lambda表达式会尝试评估1 + i,其中i是lambda表达式,因此会出现错误。 可能您想要的是在创建lambda表达式时固定i的值。您可以通过以下方法实现:
j = lambda x: x + i

使用:

j = (lambda y: lambda x: x + y)(i)
这实际上通过将变量i绑定到一个lambda变量来捕获其当前值,然后立即应用该lambda表达式,从而使绑定保持固定。

2
或者 lambda x,i=i:x + i - jonrsharpe
@jonrsharpe 是的,我认为那也可以,尽管它会允许传递第二个参数来覆盖 i 的捕获值。 - Tom Karzes
我不是故意听起来愚蠢,但如何将它应用于需要2个变量的lambda表达式?比如我的mx+b函数,其中x是会变化的变量,而b和m已经声明,但在for循环的每次迭代中都会发生变化。 - Kei
例如,如果您想捕获3个值,比如i1i2i3,那么您可以这样做:j = (lambda y1, y2, y3: lambda x: x + y1 + y2 + y3)(i1, i2, i3)。当然,在内部lambda中,您可以对它们进行任何操作,但是您已经有了这个想法。 - Tom Karzes
nums = [] j = 0 for i in range(10): j += 1 H = (lambda y: lambda x: y)(j) L = (lambda y: lambda x: H(x) + y)(i) nums.append(L) for i in nums: print(i(1))``` - Kei

5
这将给您一个线索:
>>> i=1
>>> a=lambda x:x+i
>>> a(5)
6
>>> i=2
>>> a(5)
7

lambda使用外部作用域中的 i。在 OP 的情况下,所有函数都是相同的。在最后的循环中使用 i 会使 i 成为一个函数,而不是一个整数。将其更改为其他内容,您会发现这些函数都是相同的,使用的是 i 的最后一个值:

nums = []
for i in range(10):
    j = lambda x: x + i
    nums.append(j)
for f in nums:
    print(f(1))
10
10
10
10
10
10
10
10
10
10
修复方法是将i作为函数的参数,以便将其作为本地变量捕获:
nums = []
for i in range(10):
    j = lambda x,i=i: x + i
    nums.append(j)
for f in nums:
    print(f(1))
1
2
3
4
5
6
7
8
9
10

1
这是默认参数吗?聪明的方式:) - recnac
哇,这真的很狡猾。我喜欢它。顺便感谢您的答案! - Kei

0

你的i值已经改变了,而且它不是你想象中的那个值。

首先创建lambda:

j = lambda x: x + i

希望我能保持当前值(因此为0、1、2等)。

然后执行它:

print(i(1))

你看到了吗,你把第二个迭代变量命名为i?将其改为j,你的示例就可以正常工作了。为什么?因为Python在执行lambda时解析i的值,而不是在定义时。所以当你执行你的lambda(i(1))时,它会进入你的lambda主体并尝试x + i。然后它会查找i,它现在包含你的lambda(而不是整数!)。因此出现了问题。

你需要进行双重函数才能使其正常工作。尝试这个:

if __name__ == "__main__":
  nums = []
  for i in range(10):
    def generate_lambda(i):
      return lambda x: x + i
    j = generate_lambda(i)
    nums.append(j)
  for i in nums:
    print(i(1))
为什么这个能够工作?当你调用generate_lambda时,会有一个名为i的变量与你的整数值一起使用。它将遮蔽稍后用于迭代lambda的变量i。由于你从未在generate_lambda函数内修改i变量,因此它将永远保持不变。

0

我觉得你需要学习更多关于lambda函数的知识... 实际上,它的语法是这样的:[lambda 参数: 表达式] 所以问题在于你的表达式中有两个变量,所以你需要传递两个参数。 我不太明白你想通过这个函数实现什么,但我猜想你需要为m和b设置两个参数。

在你的代码中,你需要初始化x并将其作为参数传递给lambda函数。

            nums = []
            x=0
            for i in range(10):
                j = lambda x,i : x + i
                nums.append(j)
            for i in nums:
                print(i(1,1))

0
你可以使用 operator.add 和 functools.partial,而完全不用 lambda:
import operator
import functools


if __name__ == "__main__":
    nums = []

    for i in range(10):
        nums.append(functools.partial(operator.add, i))
    for i in nums:
        print(i(1))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,