리스트 이해의 람다 함수
왜 다른 다음과 같은 두 가지 지능형리스트의 출력은, 비록입니다 f
과 lambda
동일한 기능?
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
변수 를 가리지 않고 lambda
s 에서 사용 하면 어떻게됩니까 ???
그럼 쓰레기가 발생합니다. 이거 봐요:
[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
'IT story' 카테고리의 다른 글
git : 메시지를 입력하는 동안 중단 커밋 (0) | 2020.07.18 |
---|---|
HttpURLConnection과 함께 POST를 사용하여 파일 보내기 (0) | 2020.07.18 |
안드로이드에서 화면 크기마다 dimens.xml을 정의하는 방법은 무엇입니까? (0) | 2020.07.18 |
jQuery를 사용하여 요소 ID에 특정 텍스트가 포함 된 페이지에서 모든 요소 찾기 (0) | 2020.07.18 |
Entity Framework는 고유 이름을 선택합니다 (0) | 2020.07.18 |