2010-12-13 6 views
5

에서 함수의 목록을 생성 I 익명 함수의 목록을 생성합니다 다음 파이썬 코드가있다 :파이썬

basis = [ (lambda x: n*x) for n in [0, 1, 2] ]  
print basis[0](1) 

나는 반면에, 그것은 그러나

basis = [ (lambda x: 0*x), (lambda x: 1*x), (lambda x: 2*x) ] 
print basis[0](1) 

에 해당 될 것으로 예상했을 것이다 두 번째 발췌 문장은 0을 출력하고, 첫 번째는 2를 인쇄합니다. 2. 첫 번째 코드 조각에 무엇이 잘못되었으며, 왜 예상대로 작동하지 않습니까?

+0

관련 질문 : http://stackoverflow.com/q/139819/4279 – jfs

답변

8

당신은 N에 폐쇄를 만드는 기본 매개 변수를 사용할 수 있습니다

>>> basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ]  
>>> print basis[0](1) 
0 
+3

이 기술은 메서드를 콜백 함수로 전달하는 데 자주 사용됩니다. 그것은 register_event_handler (event = evt, callback = lambda cbVar1, cbVar2, s = self : s.handle_evt (cbVar1, cbVar2))와 같은 형태로 보입니다. –

2

첫 번째 예제에서 각 람다는 동일한 n에 바인딩됩니다. 즉, 변수 값이 아니라 변수를 캡처합니다. n의 값은 루프 끝에서 2이므로, 각 람다는 n의 값 2를 사용합니다. 당신에게 새를 제공하기 위해 루프를 통해 기본 매개 변수 값은 상수이기 때문에

basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ] 
print basis[0](1) 

, n=n의 오른쪽에있는 n 평가 될 때마다 :

은 분명히이 문제를 해결하기 위해 기본 매개 변수를 사용할 수 있습니다 캡처 된 값.

+0

그 문제를 해결하는 방법에 대한 제안? – dzhelil

+1

celil : 제안 된 수정 사항을 제공하기 위해 내 대답을 편집했지만 매우 우아하지는 않습니다. – Gabe

+0

기본 매개 변수는 우아하지 않을 수도 있지만 다음과 같이 명시 적 부분 평가보다 훨씬 쉽게 볼 수 있습니다.'basis = [(λ n : (lambda x : n * x)) (n) for range (3)]'에 사용됩니다. :/기본 매개 변수는 불변이라는 의미에서 "상수"가 아니지만 평가되고 람다의'.func_defaults'에 바인딩됩니다. 클로저 매개 변수도 마찬가지지만 분명히 더 마술적인 방식으로 나타납니다. –

3

"이름으로 전달"이기 때문에. lambda 실행할 때,

, 그것은 n*x 실행 : xn은 (는 이제 2이다) 환경에서 룩업된다 (이 파라미터이다) 1에 결합된다. 그래서, 결과는 2

+0

이것은 왜 우리가 generator comprehension을 대신 사용했을 때 같은 동작이 나타나는지 설명하지 못합니다. 이것은'locals()'에 "n"이 누설되지 않습니다. AFAICT,'n'의 값은 람다의'.func_closure'에서 찾아 보았습니다. 그리고 더 이상 존재하지 않을 때 마지막으로 참조 된'n'이 마술처럼 어떻게 참조되는지는 명확하지 않습니다. –

0

내가 7에서 칼 Knechtel (12월 13일 '10에서 주석의 이해를 돕고 자 : 32). 다음 코드는 발전기를 사용하여 원래의 람다 정의는 의도 된 결과를 제공하는 방법을 보여줍니다,하지만이리스트 나 터플을 사용하지 않습니다

>>> #GENERATOR 
... basis = ((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'generator'> 
>>> basis = ((lambda x: n*x) for n in [0, 1, 2]) 
>>> print([x(3) for x in basis]) 
[0, 3, 6] 
>>> #TUPLE 
... basis = tuple((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'tuple'> 
>>> print([x(3) for x in basis]) 
[6, 6, 6] 
>>> #LIST 
... basis = list((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'list'> 
>>> print([x(3) for x in basis]) 
[6, 6, 6] 
>>> #CORRECTED LIST 
... basis = list((lambda x, n=n: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'list'> 
>>> print([x(3) for x in basis]) 
[0, 3, 6]