这个 python 函数中的 lambda 表达式是怎么回事?

发布于 2024-07-18 10:50:51 字数 621 浏览 5 评论 0原文

为什么创建柯里化函数列表的尝试不起作用?

def p(x, num):
    print x, num

def test():
    a = []
    for i in range(10):
        a.append(lambda x: p (i, x))
    return a

>>> myList = test()
>>> test[0]('test')
9 test
>>> test[5]('test')
9 test
>>> test[9]('test')
9 test

这里发生了什么?

实际上执行我期望上述函数执行的操作的函数是:

import functools
def test2():
    a = []
    for i in range (10):
        a.append(functools.partial(p, i))
    return a


>>> a[0]('test')
0 test
>>> a[5]('test')
5 test
>>> a[9]('test')
9 test

Why does this attempt at creating a list of curried functions not work?

def p(x, num):
    print x, num

def test():
    a = []
    for i in range(10):
        a.append(lambda x: p (i, x))
    return a

>>> myList = test()
>>> test[0]('test')
9 test
>>> test[5]('test')
9 test
>>> test[9]('test')
9 test

What's going on here?

A function that actually does what I expect the above function to do is:

import functools
def test2():
    a = []
    for i in range (10):
        a.append(functools.partial(p, i))
    return a


>>> a[0]('test')
0 test
>>> a[5]('test')
5 test
>>> a[9]('test')
9 test

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

幻想少年梦 2024-07-25 10:50:52

在 Python 中,在循环和分支中创建的变量没有作用域。 您使用 lambda 创建的所有函数都引用同一个 i 变量,该变量在最后一次迭代中设置为 9循环。

解决方案是创建一个返回函数的函数,从而确定迭代器变量的范围。 这就是 functools.partial() 方法起作用的原因。 例如:

def test():
    def makefunc(i):
        return lambda x: p(i, x)
    a = []
    for i in range(10):
        a.append(makefunc(i))
    return a

In Python, variables created in loops and branches aren't scoped. All of the functions you're creating with lambda have a reference to the same i variable, which is set to 9 on the last iteration of the loop.

The solution is to create a function which returns a function, thus scoping the iterator variable. This is why the functools.partial() approach works. For example:

def test():
    def makefunc(i):
        return lambda x: p(i, x)
    a = []
    for i in range(10):
        a.append(makefunc(i))
    return a
窗影残 2024-07-25 10:50:52

好吧,你也可以将 i 绑定到一个懒惰的外部 lambda 上。

def p(x, num):
    print x, num

def test():
    a = []
    for i in range(10):
        a.append((lambda i :lambda x: p (i, x))(i))
    return a

Well you can also bind the i to an outer lambda for the lazy.

def p(x, num):
    print x, num

def test():
    a = []
    for i in range(10):
        a.append((lambda i :lambda x: p (i, x))(i))
    return a
羅雙樹 2024-07-25 10:50:52

我总是很困惑为什么这不起作用。 感谢您的解释,“付费书呆子”。 我个人更喜欢这个解决方案:

for i in range(10):
    a.append(lambda num, val_i=i: p (val_i, num))

注意 lambda 的 val_i=i 默认参数,它能够在循环期间捕获 i 的瞬时值,同时仍然有效地使 lambda 成为 1 个变量的函数。 (顺便说一句:将您的 x 更改为 num 以匹配 p 的定义。)我更喜欢它,因为:

  1. 它非常接近原始版本想法并避免必须定义一个新的命名函数,这正是 lambda 的目的...
  2. 避免导入 functools
  3. 并避免叠瓦 lambda...

刚刚进行了搜索并找到了针对同一问题的更详细解释那里: python lambda 函数及其参数的范围

I was always confused as to why this doesn't work. Thanks for the explanation, 'a paid nerd'. I personally prefer this solution:

for i in range(10):
    a.append(lambda num, val_i=i: p (val_i, num))

Note the val_i=i default argument of the lambda that enables to capture the instantaneous value of i during the loop whilst still effectively making lambda a function of 1 variable. (BTW: changed your x into num to match p's definition.) I like it better because:

  1. it is very close to the original idea and avoids having to define a new named function, precisely the purpose of a lambda...
  2. avoids importing functools
  3. and avoids imbricating lambdas...

Just did a search and found more detailed explanations for the same problem there: Scope of python lambda functions and their parameters

聊慰 2024-07-25 10:50:52

我问过类似的问题,得到了两个答案。 一个与此处接受的答案基本相同,另一个不太清楚但稍微简洁一些。

在 Tkinter 中动态创建菜单。 (lambda 表达式?)

I asked a similar question, and got two answers. One basically the same as the accepted answer here, and the other which is less clear but slightly more succint.

Dynamically creating a menu in Tkinter. (lambda expressions?)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文