First mistake: command=self.s
looks for an attribute called "s". If you want to look for an attribute whose name is the content of the s variable, you should write command=getattr(self, s)
.
Second mistake: def a(self)
defines a class method called "a". If you want to programmatically generate named methods, you may do so after creating the class, with something like:
for a in x:
def fun(self):
print (a)
setattr(GUI, a, fun)
Edit: this is still wrong, because the same variable a
is used for both functions.
Anyway, it looks quite strange to generate methods that way, I’d rather have a single method that takes the content to be printed as an argument, something like:
from tkinter import *
x = ['d', 'f']
class GUI:
def __init__(self, master):
self.master = master
master.title("window")
self.label = Label(master, text="Window")
self.label.grid(columnspan=5, sticky=W+E)
self.close_button = Button(master, text="Close", command=master.destroy)
self.close_button.grid(columnspan=5, sticky=W+E)
for s in x:
self.s_button = Button(master, text=s, command=(lambda: self.print_(s)))
self.s_button.grid(columnspan=5, sticky=W+E)
def print_(self, a):
print (a)
root = Tk()
gui = GUI(root)
root.mainloop()
Edit: this is still wrong because of the s variable that is shared since the for loop does not create a new scope. Only functions create new scopes. Here is some working code:
from tkinter import *
x = ['d', 'f']
class GUI:
def __init__(self, master):
self.master = master
master.title("window")
self.label = Label(master, text="Window")
self.label.grid(columnspan=5, sticky=W+E)
self.close_button = Button(master, text="Close", command=master.destroy)
self.close_button.grid(columnspan=5, sticky=W+E)
for s in x:
self.s_button = Button(master, text=s, command=self.make_printer(s))
self.s_button.grid(columnspan=5, sticky=W+E)
def make_printer(self, a):
def fun():
print (a)
return fun
root = Tk()
gui = GUI(root)
root.mainloop()