2012-08-03 2 views
1
기본적으로

내가 루프에서 생성 OptionMenus의 시리즈를 가지고에 명령을 추가 할 수 있지만 현재 비어 :파이썬 Tkinter를 OptionMenu 여러 OptionMenus

option_menu = [] 
for ii in range(jj): 
    option_menu.append([]) 
    for ll in range(kk): 
     option_menu[ii].append(OptionMenu(frame,tkinter_text_var[ii][ll],'')) 

을 그리고 다른 곳에서 나는 따라 값을 설정하는 체크 박스를 사용 라인 :

for ii in range(jj): 
    for ll in range(kk): 
     option_menu[ii][ll]["menu"].add_command(label = name_from_box.get(), command = lambda: tkinter_text_var[ii][ll].set(name_from_box.get())) 

이 제대로 OptionMenus을 모두 채울 작동하지만이 OptionMenus의에서 값을 선택하면, 그것은 단지 option_menu [JJ] 설정 [주식] (즉, 하나를 만들어 마지막이).

그래서 내가 뭘 잘못 했습니까?

답변

4

이것은 매우 클로저와 관련된 일반적인 질문입니다. 다음 예제를보십시오 :

alist = [lambda : x for x in range(10) ] 
print (alist[2]()) #9 
print (alist[4]()) #9 

모두가 모두 9가 될 것입니다. 왜? 각 람다 함수는 변수 x을 참조하기 때문에. x은 루프를 통해 반복 될 때마다 변경되지만, 여전히 이들은 모두 동일한 개체을 참조합니다.

이 문제를 해결하는 방법 중 하나는 기본 인수를 사용하는 것입니다. 기본 인수는 호출 될 때가 아니라 함수가 작성 될 때 평가됩니다. "폐쇄와 함께 조심"-

alist = [lambda y=x: y for x in range(10) ] 
print (alist[2]()) #2 
print (alist[4]()) #4 

나는 종종 말씀 드리고

(같은 일을 할 수있는 또 다른 방법은 ... 가끔 볼 수있는 functools.partial 포함). 그들은 약간 까다로울 수 있습니다.

+0

당신이 말하는 것은 사실이지만 클로저 나 람다를 이해하지 못하는 사람에게는 대답이 혼란 스럽습니다. –

+0

@BryanOakley -이 클로저의 측면은 누구에게나 파악하기 어렵다고 생각합니다. 첫 번째 예제에서 x가 모든 람다 사이에서 공유되는 것을 명확히하려고 노력했지만 두 번째 예제에서는 그렇지 않습니다. 내가 어떻게 말할 지 모르겠다. 이해하기 쉽게하기위한 제안이 있으면 편집 (또는 더 나은 대답을 게시하면 upvote ;-)하게되어 기쁩니다. – mgilson

+0

아마도 lambda와 : 사이에있는 것이 함수 정의에서 괄호 안에있는 것과 유사하다는 것을 언급해야합니다. 즉,이 함수 호출에 대해서만 유효한 변수에 대한 바인딩입니다. 첫 번째 코드 블록의 문제는 볼 수있는 x 어딘가에 있다고 가정하고 물론 "항상"동일한 것입니다. – LJNielsenDk

관련 문제