IT story

리스트 이해의 람다 함수

hot-time 2020. 7. 18. 09:58
반응형

리스트 이해의 람다 함수


왜 다른 다음과 같은 두 가지 지능형리스트의 출력은, 비록입니다 flambda동일한 기능?

f = lambda x: x*x
[f(x) for x in range(10)]

[lambda x: x*x for x in range(10)]

둘 다 기억 type(f)하고 type(lambda x: x*x)같은 유형을 반환하십시오.


첫 번째 함수는 하나의 람다 함수를 만들고 10 번 호출합니다.

두 번째는 함수를 호출하지 않습니다. 10 가지 람다 함수를 만듭니다. 그것들을 모두 목록에 넣습니다. 처음과 동일하게 만들려면 :

[(lambda x: x*x)(x) for x in range(10)]

아니면 더 나은 :

[x*x for x in range(10)]

이 질문은 "유명한"그리고 "명백한"파이썬 구문의 매우 어려운 부분, 즉 우선 순위, 람다 또는 목록 이해력에 영향을줍니다.

OP의 목적은 0에서 9까지의 제곱 목록을 생성하는 것이 아니라고 생각합니다.이 경우 더 많은 솔루션을 제공 할 수 있습니다.

squares = []
for x in range(10): squares.append(x*x)
  • 이것은 명령형 구문의 좋은 방법입니다.

그러나 요점이 아닙니다. 요점은 W (hy) TF입니다.이 모호한 표현이 반 직관적입니까? 그리고 나는 마지막에 당신을위한 바보 사건을 가지고 있으므로, 너무 일찍 답변을 기각하지 마십시오 (나는 면접에서했습니다).

따라서 OP의 이해력은 람다 목록을 반환했습니다.

[(lambda x: x*x) for x in range(10)]

이것은 물론 제곱 함수의 10 가지 다른 사본입니다.

>>> [lambda x: x*x for _ in range(3)]
[<function <lambda> at 0x00000000023AD438>, <function <lambda> at 0x00000000023AD4A8>, <function <lambda> at 0x00000000023AD3C8>]

람다의 메모리 주소를 참고 하십시오-모두 다릅니다!

물론이 표현의 "최적"(haha) 버전을 가질 수 있습니다.

>>> [lambda x: x*x] * 3
[<function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>]

보다? 3 번 같은 람다.

변수 _사용 했습니다 for. 그것은과는 아무 상관이 없습니다 x에서을 lambda(그것은 전적으로 가려한다!). 알 겠어요?

구문 우선 순위가 그다지 중요하지 않은 이유는 무엇입니까?

[lambda x: (x*x for x in range(10))]

이는 수 : [[0, 1, 4, ..., 81]]하거나 [(0, 1, 4, ..., 81)], 또는 내가 가장 논리적 찾을 수있는 ,이는 것 list(1 개) 요소의 - a는 generator값을 반환. 그것은 사실이 아니며, 언어는 이런 식으로 작동하지 않습니다.

하지만 만약에 ...

for변수 를 가리지 않고 lambdas 에서 사용 하면 어떻게됩니까 ???

그럼 쓰레기가 발생합니다. 이거 봐요:

[lambda x: x * i for i in range(4)]

이것은 물론 수단입니다.

[(lambda x: x * i) for i in range(4)]

그러나 그것은 의미하지 않습니다.

[(lambda x: x * 0), (lambda x: x * 1), ... (lambda x: x * 3)]

이건 미친 짓이야!

목록 이해의 람다는이 이해의 범위에 대한 폐쇄입니다. 어휘 폐쇄, 그래서 그들은 참조 i참조를 통해, 그리고 그 값들은 평가 때!

따라서이 표현은 다음과 같습니다.

[(lambda x: x * i) for i in range(4)]

대략 다음과 같습니다.

[(lambda x: x * 3), (lambda x: x * 3), ... (lambda x: x * 3)]

파이썬 디 컴파일러를 사용하여 더 많은 것을 볼 수 있다고 확신합니다 (예를 들어 dis모듈을 의미 합니다).하지만 Python-VM과 무관 한 토론으로는 충분합니다. 면접 질문에 너무 많은.

이제 list승수 람다 를 만드는 방법은 실제로 연속 정수를 곱하는 것입니까? 받아 들인 대답과 마찬가지로 직접 이해 관계를 i다른 것으로 묶어서 목록 이해 표현식 에서 lambda호출 해야합니다.

전에:

>>> a = [(lambda x: x * i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
2

후:

>>> a = [(lambda y: (lambda x: y * x))(i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
1

(외부 람다 변수도 = i가 있었지만 이것이 더 명확한 해결책이라고 결정했습니다. y우리는 어느 마녀가 어느 마녀인지 알 수 있도록 소개했습니다 .)

2019-08-30 편집 :

Following a suggestion by @josoler, which is also present in an answer by @sheridp - the value of the list comprehension "loop variable" can be "embedded" inside an object - the key is for it to be accessed at the right time. The section "After" above does it by wrapping it in another lambda and calling it immediately with the current value of i. Another way (a little bit easier to read - it produces no 'WAT' effect) is to store the value of i inside a partial object, and have the "inner" (original) lambda take it as an argument (passed supplied by the partial object at the time of the call), i.e.:

After 2:

>>> from functools import partial
>>> a = [partial(lambda y, x: y * x, i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)

Great, but there is still a little twist for you! Let's say we wan't to make it easier on the code reader, and pass the factor by name (as a keyword argument to partial). Let's do some renaming:

After 2.5:

>>> a = [partial(lambda coef, x: coef * x, coef=i) for i in (1, 2)]
>>> a[0](1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() got multiple values for argument 'coef'

WAT?

>>> a[0]()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'x'

Wait... We're changing the number of arguments by 1, and going from "too many" to "too few"?

Well, it's not a real WAT, when we pass coef to partial in this way, it becomes a keyword argument, so it must come after the positional x argument, like so:

After 3:

>>> a = [partial(lambda x, coef: coef * x, coef=i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)

I would prefer the last version over the nested lambda, but to each their own...


The big difference is that the first example actually invokes the lambda f(x), while the second example doesn't.

Your first example is equivalent to [(lambda x: x*x)(x) for x in range(10)] while your second example is equivalent to [f for x in range(10)].


The first one

f = lambda x: x*x
[f(x) for x in range(10)]

runs f() for each value in the range so it does f(x) for each value

the second one

[lambda x: x*x for x in range(10)]

runs the lambda for each value in the list, so it generates all of those functions.


People gave good answers but forgot to mention the most important part in my opinion: In the second example the X of the list comprehension is NOT the same as the X of the lambda function, they are totally unrelated. So the second example is actually the same as:

[Lambda X: X*X for I in range(10)]

The internal iterations on range(10) are only responsible for creating 10 similar lambda functions in a list (10 separate functions but totally similar - returning the power 2 of each input).

On the other hand, the first example works totally different, because the X of the iterations DO interact with the results, for each iteration the value is X*X so the result would be [0,1,4,9,16,25, 36, 49, 64 ,81]


The other answers are correct, but if you are trying to make a list of functions, each with a different parameter, that can be executed later, the following code will do that:

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]

While the example is contrived, I found it useful when I wanted a list of functions that each print something different, i.e.

import functools
a = [functools.partial(lambda x: print(x), x) for x in range(10)]

for i in a:
    i()

참고URL : https://stackoverflow.com/questions/6076270/lambda-function-in-list-comprehensions

반응형