2013-10-30 2 views
3
from tkinter import * 

F=Tk() 

i=1 
while i<10: 
    newButton = Button(F,text="Show Number",command=lambda:showNumber(i)) 
    newButton.pack(side=TOP) 
    i+=1 

def showNumber(nb): 
    print(nb) 

F.mainloop() 

모든 버튼은 10을 반환합니다. 왜?
그래도 @abernert가 지적 하듯, 그들이있어 (폐쇄 등이 될 수
나에게가변 매개 변수가있는 콜백 함수 tkinter 버튼

답변

5

익명 lambda 기능을 도와 주셔서 감사합니다 ... 복귀 1, 버튼 2 복귀 2 버튼 1 원함 실제로는 클로저가 파이썬의 경우는 없습니다.) - 나중에 변수를 참조하기 위해 변수 i을 "닫습니다". 그러나 그들은 정의 시간에 값을 검색하지 않고,을 호출 할 때 다음에 다음에 while 루프가 끝난 시점에서 (i은 10과 같습니다) 을 조회합니다. .

이 문제를 해결하려면 람다가 사용할 다른 값으로 i 값을 다시 바인딩해야합니다. 당신은 여러 가지 방법으로이 작업을 수행 할 수 있습니다 - 여기 하나 :

... 
i = 1 
while i < 10: 
    # Give a parameter to the lambda, defaulting to i (function default 
    # arguments are bound at time of declaration) 
    newButton = Button(F, text="Show Number", 
     command=lambda num=i: showNumber(num)) 
    ... 
+0

대단히 감사합니다! :) – superyo40

+0

실제로는 여기에 클로저가 없기 때문에 이것은 정확하지 않습니다. 그러나 이것은 내 것보다 간결한 설명이며, 초보자가 이해하기 쉽기를 바랍니다. – abarnert

+0

@abarnert : 그것을 언급 해 주셔서 고마워요. - 저에게 StackOverflow를 즐기고 그 과정에서 배울 수있는 그런 작은 기술이 있습니다. – voithos

5

이것은 파이썬 질문에 설명되어 있습니다 : Why do lambdas defined in a loop with different values all return the same result?.


의 FAQ 대답을 인용 : x는 람다 로컬이 아니라 외부 범위에 정의되며,이 람다가 호출 될 때 액세스 할 수 있기 때문에

이 발생 -하지 않을 때 그것을 이를 방지하기 위해 ...

을 정의, 당신은 ... 그들은 세계의 값에 의존하지 않는 있도록 람다에 지역 변수의 값을 저장해야

즉, 새 함수는 i값을 저장하지 않고 변수 i을 저장합니다. 그리고 그들은 모두 변수 i을 저장하고 있습니다. 루프의 끝에는 10 값이 있습니다. 실제로 F.mainloop() 앞에 i = 'spam'을 추가하면 모든 버튼이 숫자 대신 spam 문자열을 출력합니다.

이것은 클로저를 만들려고 할 때 매우 유용합니다. 즉, 정의 된 환경에 영향을 줄 수있는 기능입니다. * 그렇지만 이 아닌 경우이 그렇게하려고 할 때 방해가 될 수 있습니다.

가장 간단한 방법은 매개 변수를 기본값과 함께 사용하는 것입니다. 기본값은 변수를 보유하지 않습니다. 함수가 정의 될 때 평가되는 값. 그래서 : i 오히려 둘러싸 범위에서 지역보다 글로벌이기 때문에

newButton = Button(F,text="Show Number", command=lambda num=i: showNumber(num)) 

은 *, 관련된 모든 폐쇄가 실제로 존재하지 않습니다,이 경우 모릅니다. 그러나 실제로 이것은 파이썬이 전역을위한 특별한 처리를하고 여기에 클로저가 필요 없기 때문입니다. 개념적으로 하나가 있다고 생각하면 __closure__ 또는 __code__ 속성을 살펴보기 전에는 문제가 발생하지 않습니다.

+0

감사합니다! :) 그것은 작동합니다! – superyo40

+0

좋은 점은 파이썬이 모듈 수준의 변수를 다르게 처리한다는 것을 몰랐습니다. – voithos

관련 문제