以下表达式实际上做了什么?
list = [lambda n=n: lambda x: x+n for n in range(10)]
更具体地说:
n=n
是什么意思?'list'
的输出是什么
print(list[0](14))
和print(list[0]()(14))
为什么?
答案 0 :(得分:3)
- 醇>
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。
- 的内容是什么? 醇>
list
list
将是一个可选参数的10个函数,其默认值的范围为0到9,每个参数返回一个参数的函数。返回的函数是来自外部函数的n
值的闭包。因此,当它被调用时,它返回其参数x
,加上范围为0到9的n
变量。
- 的输出是什么 醇>
print(list[0](14))
在这里,你用参数14调用第一个外部函数list[0]
。因此,n
代替它的默认值0,它将有14个。所以,你是什么的'll get是一个函数,它接受一个参数并向其添加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)
会告诉您它在名称n
下隐藏了数字14以供其内部函数使用。
...
print(list[0]()(14))
在这里,您再次调用list[0]
,但这次没有参数,因此其n
获取默认值0
。因此,它返回一个向其参数添加0
的函数。然后,您使用14
调用该函数,以便获得14
。
答案 1 :(得分:0)
首先回答最后一部分:
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的索引,n = n本地的lambda。