Search on blog:

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
If you like it
Buy a Coffee