blog.furas.pl
# prywatne notatki - Python, Linux, Machine Learning, etc.

Wyrażenie lambda w command= przy przypisywaniu funkcji do widgeta w Tkinter

To jest "przedruk" jednej z moich wypowiedzi na polskim forum Pythona. http://pl.python.org/forum/index.php?topic=4366.msg18668#msg18668


Poniższy opis odnosi się np. do kodu

Button(master, text="Wcisnij", command=...)

Do przekazywania argumentów w command przydatna staje sie funkcja lambda

... command=self.onButton  # bez nawiasów

... command=lambda:self.onButton() # z nawiasami

... command=lambda:self.onButton(1,2,3)

Poniższe przypadki akurat w command nie są przydatne (bo command oczekuje funkcji, która nie wymaga przekazywania agumentów) ale gdyby była potrzeba przypisania funkcji, do której będą przekazywane np. trzy argumenty a my mamy funkcje, która wymaga więcej lub mniej argumentów to:

... command=lambda x,y,z:self.onButton(1,2,3,x,y,z)
... command=lambda x,y,z:self.onButton()

Można też przypisać wartości domyślne argumentom i w przypadku command poniższe przypadki będą sobie równe

... command=lambda x=1,y=2,z=3:self.onButton(x,y,z)
... command=lambda:self.onButton(1,2,3)

Wartość można też wstawić tak

numer =  4
... command=lambda:self.onButton(numer)

ale do onButton nie zostanie wstawiona na stałe wartość zmiennej numer tylko przy każdym wywołaniu tej funkcji lambda będzie tam wstawiana aktualna wartość zmiennej numer

Tak więc w takim przypadku

numer =  4
... command=lambda:self.onButton(numer)
numer =  99

może się okazać, że onButton jako argument dostanie wartość 99. W pewnych przypadkach może to być nawet przydatne ale na pierwszy rzut oka nie takiej reakcji się spodziewany.

Widać to szczególnie w takim przypadku

for numer in range(1,4):
     ... command=lambda:self.onButton(numer)

Okazuje się, że powyższe nie będzie równoważne z

... command=lambda:self.onButton(1)
... command=lambda:self.onButton(2)
... command=lambda:self.onButton(3)

tylko z

... command=lambda:self.onButton(4)
... command=lambda:self.onButton(4)
... command=lambda:self.onButton(4)

bo po przejściu pętli zmienna numer będzie miała wartość 4

Aby otrzymać oczekiwany wynik trzeba to zrobić tak

for numer in range(1,4):
     ... command=lambda x=numer:self.onButton(x)

podobnie jak tutaj

numer =  4
... command=lambda liczba=numer:self.onButton(liczba)
numer =  99
Książki: python-dla-kazdego-podstawy-programowania python-wprowadzenie python-leksykon-kieszonkowy python-receptury python-programuj-szybko-i-wydajnie python-projekty-do-wykorzystania black-hat-python-jezyk-python-dla-hackerow-i-pentesterow efektywny-python-59-sposobow-na-lepszy-kod tdd-w-praktyce-niezawodny-kod-w-jezyku-python aplikacje-internetowe-z-django-najlepsze-receptury