0

I'm trying to call same function with different argument with correspond to for in and buttons in Tkinter python, and when I click the other buttons the value given by the function is the last calls value . I'm a js dev where have used foreach and array with similar thing.

apps=["k","c","d"] 
for app in apps:
        btn = tk.Button(innerFrame, text=" {}".format(app), command=(
            lambda: runThis(app)))
        btn.pack()
       
def runThis(val, i):
    print("Value of the btn {}".format(val))

the expected output when I click each button is

Value of the btn k
Value of the btn c
Value of the btn d

but what I get is

Value of the btn d
Value of the btn d
Value of the btn d
Magnus Melwin
  • 1,509
  • 1
  • 21
  • 32
rbkavin
  • 69
  • 7
  • Does this answer your question? [List comprehension and lambdas in Python](https://stackoverflow.com/questions/45925683/list-comprehension-and-lambdas-in-python) – quamrana Jul 31 '20 at 12:43
  • 1
    Be aware that the function in your example `runThis` accepts two params `val, i` but you are supplying only one in the button's lambda part `lambda: runThis(app)`. – Wereii Jul 31 '20 at 12:51

1 Answers1

3

Since app is a pointer to an object, and it gets overwritten in the loop, the last element in the list will be the value tk stores.

btn = tk.Button(innerFrame, text=name, command=lambda app=app: runThis(app))

This copies the object, therefore app won't get overwritten in your loop.


Think about it this way. In your loop:

#first loop
app = "k"
function(points to -> app -> points to "k") #first

#second loop
app = "c"
function(points to -> app -> points to "c") #first
function(points to -> app -> points to "c") #second

#third loop
app = "d"
function(points to -> app -> points to "d") #first
function(points to -> app -> points to "d") #second
function(points to -> app -> points to "d") #third

Therefore you need to copy the content of app, to avoid overwriting already existing values.

nagyl
  • 1,644
  • 1
  • 7
  • 18
  • Might as well check out [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial) instead of lambdas for this usecase. – Wereii Jul 31 '20 at 12:50