왜 다른 다음과 같은 두 가지 지능형리스트의 출력은, 비록입니다 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 편집 :
@sheridp의 답변에도있는 @josoler의 제안에 따라 목록 이해 “루프 변수”의 값을 객체 내부에 “내장”할 수 있습니다. 키는 적시에 액세스해야합니다. 위의 “After”섹션은 다른 것으로 래핑 lambda
하고 현재 값인 즉시 호출하여 수행합니다 i
. 또 다른 방법은 (조금 더 읽기 쉬운- ‘WAT’효과를 생성하지 않음) 객체 i
내부 의 값을 저장 partial
하고 “내부”(원본) lambda
를 인수로 사용하는 것입니다.partial
로 사용하는 것입니다. 통화 시간), 즉 :
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)
훌륭하지만 여전히 약간의 비틀기가 있습니다! 코드 리더에서 더 쉽게 만들고 싶지 않다고 말하고 요소를 키워드 인수로partial
. 이름을 바꾸자 :
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'
와트?
>>> a[0]()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'x'
잠깐만 … 인수 개수를 1 씩 바꾸고 “너무 많음”에서 “너무 작음”으로 바뀌고 있습니까?
음, 진짜 WAT는 우리가 통과 할 때, 아니다 coef
에 partial
이 방법으로는 위치 후에 와야하므로,이 키워드 인수는,이된다 x
과 같이, 인수 :
3시 이후
>>> a = [partial(lambda x, coef: coef * x, coef=i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)
중첩 된 람다보다 마지막 버전을 선호하지만 각 버전마다 선호합니다.
답변
가장 큰 차이점은 첫 번째 예제는 실제로 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)]
f()
범위의 각 값에 대해 실행되므로 각 값에 f(x)
대해 수행됩니다.
두 번째
[lambda x: x*x for x in range(10)]
목록의 각 값에 대해 람다를 실행하여 해당 함수를 모두 생성합니다.
답변
사람들은 좋은 대답을했지만 내 의견으로는 가장 중요한 부분을 언급하는 것을 잊었습니다. 두 번째 예 X
에서 목록 이해 X
의 lambda
기능 은 기능 의 기능 과 동일하지 않으며 완전히 관련이 없습니다. 두 번째 예는 실제로 다음과 같습니다.
[Lambda X: X*X for I in range(10)]
내부 반복 range(10)
은 목록에 10 개의 유사한 람다 함수 (10 개의 개별 함수이지만 완전히 유사 함-각 입력의 거듭 제곱 2를 반환 함) 만 생성합니다.
반면에 첫 번째 예제는 반복의 X가 결과와 상호 작용하기 때문에 완전히 다른 방식으로 작동합니다. 각 반복마다 값이 X*X
있으므로 결과는 다음과 같습니다.[0,1,4,9,16,25, 36, 49, 64 ,81]
답변
다른 대답은 정확하지만 나중에 다른 매개 변수를 가진 함수 목록을 만들려고하면 나중에 실행할 수 있습니다 . 다음 코드는이를 수행합니다.
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]
예제가 고안되었지만, 각각 다른 것을 인쇄하는 함수 목록을 원할 때 유용합니다.
import functools
a = [functools.partial(lambda x: print(x), x) for x in range(10)]
for i in a:
i()