Python Forum
dynamic variable name declaration in OOP style project problem - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: dynamic variable name declaration in OOP style project problem (/thread-40965.html)



dynamic variable name declaration in OOP style project problem - jacksfrustration - Oct-21-2023

Ok so basically im trying to build a flight tracker app. And i have a problem with the gui py file. I have a button that generates variable names using fstrings. an example follows


globals()[f'city_lbl{self.count}'] = Label(text="City to fly to : ")
globals()[f"city_lbl{self.count}"].grid(row=self.cur_row, column=0)
i want to give the user the ability to enter multiple destination names and create a dataframe on another py file that includes time the trip can start and by when you have to be back, as well as, generate IATA codes for each supplied city. I want to be able to save this dataframe in a csv file that can also be read using a different button.

my problem arises when i try to extract all of the city names supplied by the user i create a for loop with the range function (maximum being the self.count variable) and i append the resulting value in a list for further examination. so i have the following code



saved_info=[]
for i in range(0,self.count):
    city_name=globals()[f"city_ent{i}"].get().title()
my problem is i get an error code of Key Error that follows

Error:
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\giorg\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__ return self.func(*args) ^^^^^^^^^^^^^^^^ File "C:\Users\giorg\PycharmProjects\pythonProject2\day_39_udemy\gui.py", line 59, in save_ent if globals()[f"city_ent{i}"].get(): ~~~~~~~~~^^^^^^^^^^^^^^^^ KeyError: 'city_ent0'
im guessing this means that it cant find the assigned entry even though i have generated that entry with the following code. now if i was to guess is that because the assigned entry is using self. before the declaration. i have tried putting self. in front of the dynamic declaration (that uses globals() and uses a key to generate the variable name) but it wouldn't work. can someone help me? I want to make this app OOP style that contain py files with classes on each but in order to access the parameters like variable values and such self. has to be used otherwise it is not accessible past the initialization phase of the class


self.city_ent0 = Entry()
self.city_ent0.grid(row=1, column=1)



RE: dynamic variable name declaration in OOP style project problem - deanhystad - Oct-21-2023

I have yet to see code where dynamically creating variables was a good idea. Why make variables named city_lbl1, city_lbl2 instead of making a list city_lbl? Having a list makes it really easy to loop through all the names.


RE: dynamic variable name declaration in OOP style project problem - jacksfrustration - Oct-22-2023

(Oct-21-2023, 10:25 PM)deanhystad Wrote: I have yet to see code where dynamically creating variables was a good idea. Why make variables named city_lbl1, city_lbl2 instead of making a list city_lbl? Having a list makes it really easy to loop through all the names.
how would i go about doing that? im making dynamic variables because i want to keep adding columns of information. i really dont know how else to do it


RE: dynamic variable name declaration in OOP style project problem - deanhystad - Oct-22-2023

Post what you have done so far. Your previous examples do not show why you would need dynamic variables.

Looking at your previous code I would do something like this:
import tkinter as tk


class Form(tk.Tk):
    def __init__(self, fields):
        super().__init__()
        self.fields = fields
        for row, (field, text) in enumerate(fields.items()):
            tk.Label(self, text=text).grid(row=row, column=0, sticky="e")
            entry = tk.Entry(self, width=30)
            entry.grid(row=row, column=1, sticky="w")
            self.fields[field] = entry

        tk.Button(
            self, text="Print Fields", command=self.print_fields
        ).grid(row=row+1, column=0, columnspan=2, sticky="ew")

    def print_fields(self):
        for name, entry in self.fields.items():
            print(name, entry.get())


fields = {
    "departure": "Leaving from city",
    "destination": "City to fly to",
}
Form(fields).mainloop()
That might be way off base, but it is how I would make a window where the widgets are defined by something outside the window's code. Essentially I am creating dynamic variables in the class scope, but I control what widgets are in that namespace. Everything in self.fields will be an entry widget. I can loop over the widgets by looping over the values in the dictionary.