Это из-за того, как ваш кадр "обновляется". Вы определяете страницу здесь, и когда вы настраиваете все кнопки и все, вы go через все for
l oop, прежде чем все будет визуализировано. При этом command
будет последним значением в вашем l oop, 5
. По сути, он будет делать это:
def f(n):
return n
def list_of_functions():
x = []
for i in range(5):
x.append(lambda: f(i))
return x
for func in list_of_functions():
func()
4
4
4
4
4
Это поведение функций в целом, потому что оно принимает значение numberOfEntries
, которое вы в последний раз определили, а не то, которое, по вашему мнению, было определено. Чтобы показать это с помощью эквивалентной «нормальной» функции:
# Note that there's no argument here, because
# you haven't given your lambda an argument
def f():
# does a global lookup for value g
return g
def create_funcs():
funcs = []
for g in range(5):
funcs.append(f)
return funcs
for func in create_funcs():
func()
4
4
4
4
4
Обходной путь здесь заключается в том, чтобы физически связать это значение с функцией во время определения . Это можно сделать с помощью functools.partial
. Чтобы сначала показать простой пример:
from functools import partial
def f(n):
return n
def list_of_functions():
x = []
for i in range(5):
x.append(partial(f, i))
return x
for func in list_of_functions():
func()
0
1
2
3
4
Или, вы можете добавить входной аргумент к своей лямбде и привязать к нему значение по умолчанию:
def f(n):
return n
def list_of_functions():
x = []
for i in range(5):
# note that now we have bound an input argument to our lambda
x.append(lambda i=i: f(i))
return x
for func in list_of_functions():
func()
0
1
2
3
4
Теперь каждый вызов изменяется соответствующим образом. Чтобы показать, как реализовать это в вашем коде:
from functools import partial
def refreshFrame():
global frame
global Values
frame.destroy()
frame = tk.Frame(mainGuiWindow)
frame.pack()
tk.Label(frame,text="Sl. No").grid(row=0,column=0)
tk.Label(frame,text="Value").grid(row=0,column=1)
tk.Label(frame,text="Print Entry").grid(row=0,column=2)
# I've changed this to be a bit more idiomatic
for n, (entry, *_) in enumerate(Values, start=1):
tk.Label(frame,text=n).grid(row=n, column=0)
tk.Label(frame,text=entry).grid(row=n, column=1)
# this *looks* like a lambda, and still returns a function
# but binds the value of `n` to the function, rather than relying
# on references to a variable that you've changed
tk.Button(frame, text="Print",command=partial(printValue, n)).grid(row=n, column=2)