How do I create objects dynamically in Python?

Question:

I want to be able to have multiple entries with unique Return functions in my program using tkinter.

What I have right now is a for loop with the following:

...
parent = Frame(self, ...)

# values is a dictionary containing a name for each Label  
# and a list of user input and a certain command

for key, value in values.items():
    temp_name_frame = Frame(parent)  
    temp_name_frame.pack(fill="none", expand="no", anchor='w')  

    temp_name_label = Label(temp_name_frame, text=key, width=30, anchor='w')  
    temp_name_label.pack(side=LEFT, anchor='w')  

    temp_name_entry = Entry(temp_name_frame, width=20)  
    temp_name_entry.pack(side=LEFT)
    temp_name_entry.insert(END, value[0])
    temp_name_entry.bind('<Return>', lambda e: send_command(value[1]))     
...

Exptected Outcome:
When I run the program the expected outcome is a Frame parent with multiple frames temp_name_frame inside. In each of those frames a Label temp_name_label with text key and Entry temp_name_entry with value value[0] is present and each Entry has a unique command value[1] on Return.

Actual Outcome:
When I run the program the outcome is a Frame parent with multiple frames temp_name_frame inside. In each of those frames a Label temp_name_label with text key and Entry temp_name_entry with value value[0] is present, but each Entry has the last command value[1] from the values dictionary on Return.

I believe this is because each Frame, Label and Entry is overwritten because the name of each variable stays the same (temp_name_frame, temp_name_label, temp_name_entry)

But if that is true, why do I have multiple Labels and Entries with the correct Label text and Entry value?

Another example explained without code:
I have 3 Labels that have an indentifying name as text like Unique command 1 Label, Unique command 2 Label and Unique command 3 Label respectively.
I have 3 Entries that on return print something like Unique command 1, Unique command 2 and Unique command 3 respectively and each Entry value on startup is 1, 2, and 3 respectively.

Outcome:
Each Label has the correct text: Unique command 1 Label, Unique command 2 Label, Unique command 3 Label
Each Entry has the correct value at startup (1, 2 and 3)
BUT each Entry returns ‘Unique command 3’

Asked By: pietjanssen

||

Answers:

This is often referred to as reflection or sometimes introspection. Check out a similar questions that have an answer for what you are trying to do:

Does Python Have An Equivalent to Java Class forname

Can You Use a String to Instantiate a Class in Python

Answered By: Yash Soni

You have run into a fairly common problem of late binding in Python. You can read this post for more details.

Basically you need to force a closure in your lambda function, like so:

...

def send_command(event, string): #just a made up function
    print (string)

for key, value in values.items():
    ...
    temp_name_entry.bind('<Return>', lambda e, v=value[1]: send_command(e, v))
Answered By: Henry Yik
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.