Help with two issues, buttons and second class object

Peter Otten __peter__ at web.de
Fri Nov 25 05:58:27 EST 2016


Thomas Grops via Python-list wrote:

> Peter, in your code what does that self.root = root mean in the __init__
> function of the class

In your original script you used global variables to access the tkinter.Tk() 
object and the canvas. A simplified example:

import tkinter

class Tank:
    def make_button(self):
        tkinter.Button(root).pack()

root = tkinter.Tk() # you used the name "main" instead of "root"
tank = Tank()
tank.make_button()
root.mainloop()

Programmers with a little experience tend to avoid globals, so let's put the 
script code above into a function:

import tkinter

class Tank:
    def make_button(self):
        tkinter.Button(root).pack()

def main():
    root = tkinter.Tk() # you used the name "main" instead of "root"
    tank = Tank()
    tank.make_button()
    root.mainloop()

main()

When you run the above you'll get a NameError. Because make_button() 
accesses root which is no longer global you have to find a way to pass it to 
the tank instance. One way is to change the make_button() method and pass it 
along as an argument:

class Tank:
    def make_button(self, root):
        tkinter.Button(root).pack()

def main():
    root = tkinter.Tk() 
    tank = Tank()
    tank.make_button(root)
    root.mainloop()

The other way (the one I used) is to make it an attribute of the tank 
instance:

class Tank:
    def __init__(self, root):
        self.root = root
    def make_button(self):
        tkinter.Button(self.root).pack()

def main():
    root = tkinter.Tk() 
    tank = Tank(root)
    tank.make_button()
    root.mainloop()

Now you can access root as self.root in every method of the Tank class. 
There is no advantage in this case, but when root is referred in more than 
one place, either in the class or by the code invoking methods of the class, 
it will be more convenient.

An important advantage of using an explicit argument instead of a global is 
that different instances can have different values for root. For a Tank that 
might be battlefields

def main():
    root = tkinter.Tk()
    other = tkinter.Toplevel()

    for battlefield in root, other:
        tank = Tank(battlefield)
        tank.make_button()

    root.mainloop()

Note that this requires no change of the Tank class.




More information about the Python-list mailing list