【问题标题】:Please help me translate the following lambda to human language请帮我将以下 lambda 翻译成人类语言
【发布时间】:2014-12-13 08:33:41
【问题描述】:

下面的表达式实际上做了什么?

list = [lambda n=n: lambda x: x+n for n in range(10)]

更具体地说:

  1. n=n 是什么意思?
  2. 'list'的内容是什么?
  3. 的输出是什么

    print(list[0](14))print(list[0]()(14))

为什么?

【问题讨论】:

  • 与其问输出结果如何,不如试试看?
  • 运行它。 “为什么?”是真正的麻烦...

标签: python lambda expression


【解决方案1】:
  1. n=n 是什么意思?

lambda 允许您定义带参数的函数,就像def。这些参数可以有default argument values。所以,lambda n=n:def foo(n=n): 相同。

事实上,当面对一个您无法阅读的复杂表达式时,通常值得将其分解为简单的语句:

list = []
for n in range(10):
    def spam(n=n):
        def eggs(x):
            return x+n
        return eggs
    list.append(spam)

现在,为什么要创建一个名为 n 且默认值为 n 的参数?为什么不只是lambda:The official FAQ 解释了这一点,但让我们试着总结一下。

如果你只是这样写:

funcs = [lambda: n for n in range(10)]

...你得到的是 10 个无参数函数,它们都是对同一个变量 n 的闭包。因为n在循环结束时的值为9,所以当被调用时,它们都将返回9。

但如果你这样做:

funcs = [lambda n=n: n for n in range(10)]

... 你得到的是一个可选参数n 的10 个函数(它从视图中隐藏了闭包n),其默认值是定义每个函数时n 的值。因此,当不带参数调用时,第一个将返回 0,第二个将返回 1,依此类推。

当然,在您的情况下,这些函数不仅仅是返回n,它们还返回一个接受参数、将n 添加到其中并返回结果的函数。但想法是一样的;您希望它们返回不同的函数,它们将 0、1、... 9 添加到它们的参数中,而不是所有返回的函数都添加 9。


  1. list 的内容是什么?

list 将是一个可选参数的 10 个函数,其默认值范围从 0 到 9,每个函数返回一个参数的函数。返回的函数是对外部函数的 n 值的闭包。因此,当它被调用时,它会返回其参数 x,以及范围从 0 到 9 的 n 变量。


  1. 的输出是什么
print(list[0](14))

在这里,您使用参数 14 调用第一个外部函数 list[0]。因此,n 的默认值不是 0,而是 14。所以,您将得到的是一个函数,它接受一个参数并将 14 添加到它。但它会打印出如下内容:

<function <listcomp>.<lambda>.<locals>.<lambda> at 0x105f21f28>

Python 3.4+ 试图通过告诉你在哪里找到函数定义来提供帮助。 通常,当一个函数嵌套这么深时,沿途的大部分步骤都有名称。在这种情况下,你有三层匿名函数,所以没有一个名字很有用……

为了看到它做任何有用的事情,你必须调用它:

print(list[0](14)(20))

这会给你34

您也可以使用inspect 模块,或者只是dir,在函数内部进行探索。例如,print(list[0](14).__code__.co_freevars[0], list[0](14).__closure__[0].cell_contents) 会告诉您它已将数字 14 隐藏在名称 n 下,供其内部函数使用。

print(list[0]()(14))

在这里,您再次调用list[0],但这次没有参数,所以它的n 获得0 的默认值。因此,它返回一个将0 添加到其参数的函数。然后用14 调用该函数,得到14

【讨论】:

    【解决方案2】:

    先回答最后一部分:

    In [1]: list = [lambda n=n: lambda x: x+n for n in range(10)]
    
    In [2]: print(list[0](14))
    <function <lambda> at 0x7f47b5ca7cf8>
    
    In [3]: print(list[0]()(14))
    14
    

    通过运行代码获得。 list 顺便说一句,名字不好,因为 list 是 python 内置的 给你 10 个 lambda 函数,它们做的不多 - 第一个将返回原始参数 x,第二个参数 + 1,等等.因为 n 存储为 lambda 的索引,由 lambda 本地的 n=n 存储。

    【讨论】: