为什么以下两个列表推导的输出不同,即使f和lambda函数相同?
f = lambda x: x*x
[f(x) for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
和
[lambda x: x*x for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
请注意,类型(f)和类型(lambda x:x*x)都返回相同的类型.
Win*_*ert 227
第一个创建一个lambda函数并调用它十次.
第二个不调用该函数.它创建了10种不同的lambda函数.它将所有这些放在一个列表中.使它等同于你需要的第一个:
[(lambda x: x*x)(x) for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
或者更好的是:
[x*x for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
Tom*_*dor 81
这个问题涉及"着名的"和"明显的"Python语法的一个非常臭的部分 - 什么优先,lambda或列表理解的for.
我不认为OP的目的是生成从0到9的正方形列表.如果是这种情况,我们可以提供更多解决方案:
squares = []
for x in range(10): squares.append(x*x)
Run Code Online (Sandbox Code Playgroud)
但这不是重点.重点是W(hy)TF是这个模糊的表达所以反直觉吗?最后,我有一个愚蠢的案例,所以不要过早地解雇我的答案(我在面试时有这个问题).
所以,OP的理解返回了一个lambdas列表:
[(lambda x: x*x) for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
这当然只是10个不同的平方函数副本,请参阅:
>>> [lambda x: x*x for _ in range(3)]
[<function <lambda> at 0x00000000023AD438>, <function <lambda> at 0x00000000023AD4A8>, <function <lambda> at 0x00000000023AD3C8>]
Run Code Online (Sandbox Code Playgroud)
注意 lambda的内存地址 - 它们都是不同的!
你当然可以拥有这个表达式的更"最优"(haha)版本:
>>> [lambda x: x*x] * 3
[<function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>]
Run Code Online (Sandbox Code Playgroud)
看到?3次相同的 lambda.
请注意,我用_的for变量.它没有任何跟x在lambda(它在词法黯然失色!).得到它?
我要省略讨论,为什么语法优先级不是这样,这一切都意味着:
[lambda x: (x*x for x in range(10))]
Run Code Online (Sandbox Code Playgroud)
这可能是:[[0, 1, 4, ..., 81]],或者[(0, 1, 4, ..., 81)],或者我认为最符合逻辑的,这将是list1个元素 - generator返回值.事实并非如此,语言不会这样.
但是,如果......
如果你不掩饰for变量怎么办,并在你的lambdas中使用它?
好吧,然后发生了废话.看这个:
[lambda x: x * i for i in range(4)]
Run Code Online (Sandbox Code Playgroud)
这当然意味着:
[(lambda x: x * i) for i in range(4)]
Run Code Online (Sandbox Code Playgroud)
但它并不意味着:
[(lambda x: x * 0), (lambda x: x * 1), ... (lambda x: x * 3)]
Run Code Online (Sandbox Code Playgroud)
这太疯狂了!
列表理解中的lambdas是对这种理解范围的封闭.一个词汇封闭,因此它们指的是i通过引用,而不是它们在评估时的价值!
所以,这个表达式:
[(lambda x: x * i) for i in range(4)]
Run Code Online (Sandbox Code Playgroud)
大致等同于:
[(lambda x: x * 3), (lambda x: x * 3), ... (lambda x: x * 3)]
Run Code Online (Sandbox Code Playgroud)
我相信我们可以在这里看到更多使用python反编译器(我的意思是例如dis模块),但对于Python-VM不可知的讨论,这就足够了.求职面试的问题非常多.
现在,如何制作list乘数lambdas,它真正乘以连续的整数?好吧,类似于接受的答案,我们需要i通过将其包装在另一个中来打破直接联系lambda,这将在列表理解表达式中被调用:
之前:
>>> a = [(lambda x: x * i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
2
Run Code Online (Sandbox Code Playgroud)
后:
>>> a = [(lambda y: (lambda x: y * x))(i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
1
Run Code Online (Sandbox Code Playgroud)
(我还有外部lambda变量= i,但我认为这是更清晰的解决方案 - 我介绍了y所以我们都可以看到哪个女巫是哪个).
Gab*_*abe 18
最大的区别是第一个例子实际上调用了lambda f(x),而第二个例子却没有.
你的第一个例子相当于[(lambda x: x*x)(x) for x in range(10)]你的第二个例子相当于[f for x in range(10)].
第一个
f = lambda x: x*x
[f(x) for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
运行f()范围中的每个值,以便f(x)为每个值执行
第二个
[lambda x: x*x for x in range(10)]
Run Code Online (Sandbox Code Playgroud)
为列表中的每个值运行lambda,因此它生成所有这些函数.
其他的答案是正确的,但如果你试图使功能列表,每一个不同的参数,可以被执行后,下面的代码将做到这一点:
import functools
a = [functools.partial(lambda x: x*x, x) for x in range(10)]
b = []
for i in a:
b.append(i())
In [26]: b
Out[26]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Run Code Online (Sandbox Code Playgroud)
虽然这个例子是人为的,但当我想要一个函数列表时,我发现它很有用,每个函数都打印不同的东西,即
import functools
a = [functools.partial(lambda x: print(x), x) for x in range(10)]
for i in a:
i()
Run Code Online (Sandbox Code Playgroud)
小智 6
人们给出了很好的答案,但忘记了我认为最重要的部分:在第二个示例X中,列表理解X的lambda功能与函数的不同,它们是完全无关的。因此,第二个示例实际上与以下示例相同:
[Lambda X: X*X for I in range(10)]
Run Code Online (Sandbox Code Playgroud)
内部迭代range(10)仅负责在列表中创建10个相似的lambda函数(10个独立的函数,但完全相似-返回每个输入的幂2)。
在另一方面,第一个例子中的作品完全不同,因为重复的X与结果进行交互DO,每次迭代的值是X*X这样的结果将是[0,1,4,9,16,25, 36, 49, 64 ,81]