[Tutor] OOP help needed

Alan Gauld alan.gauld at yahoo.co.uk
Wed Jul 27 05:04:43 EDT 2016


On 27/07/16 04:44, Jim Byrnes wrote:
> OOP has always driven me crazy.  I read the material and follow the 
> examples until I feel I understand them, but when I try to implement it 
> I end up with an error filled mess.

That suggests that its not the OOP concept thats confusing
you but the language syntax. How to turn the concept into code?

> So I decided to give it another try.  When I got to the chapter on 
> tkinter I decided to solve all the exercises using OOP even though the 
> book solutions did not use OOP. The first one went fine:

Actually not as fine as you thought. In effect you got lucky by
making a mistake that still resulted in your code doing
approximately what you expected. But it didn't really do
what you thought it did.

> import tkinter
> 
> class Goodbye:
>    def __init__(self):
> 
>      self.frame = tkinter.Frame(window)
>      self.frame.pack()

You are using a global variable as your parent here. It would be
better to pass that in as an argument. Or better still to make
the call to Tk() inside the __init__ method. That's not really
an OOP thing though just a general good practice issue.
It's best to avoid relying on global variables in your
functions.

>      self.goodbye_button = tkinter.Button(self.frame, text='Goodbye',
>        #command=quit)
>        command=lambda: quit() )
>      self.goodbye_button.pack()

Here you assign quit to the button's command. That's OK because
there is a top level built-in function called quit which exits
the interpreter. It's a bit of a brutal way to exit your GUI
but it works.

But I guess you really wanted to call your quit method. Remember
to access anything in your class you have to use the self
prefix, so you should have said:

command=self.quit

or

command=lambda: self.quit()

Lambda doesn't really help in this case but it doesn't do
any harm either.

>    def quit():
>      self.window.destroy()

When you define a method inside a class you need to
explicitly include the self parameter. So this should be:

    def quit(self):
      self.window.destroy()

But there's a snag, you don't store the window inside the
class. So self.window will cause an error. You either need
a line like

self.window = window

in your__init__ method

or use the global window variable like

    def quit():
      window.destroy()

My preference would be to create a self.window instance variable,
inside init()then access the self.window in quit(). You would also
call mainloop() using self.window in your init()

> if __name__=='__main__':
>    window = tkinter.Tk()
>    myapp = Goodbye()
>    window.mainloop()

So if you took my advice this section of code would look like:

if __name__=='__main__':
    Goodbye()


and init() would look like:

def __init__(self):
     self.window = tkinter.Tk()
     self.frame = tkinter.Frame(self.window)
     self.frame.pack()

     self.goodbye_button = tkinter.Button(self.frame, text='Goodbye',
                                          command=self.quit)
     self.goodbye_button.pack()

     self.window.mainloop()

If you read through that and understand it, it should give
you the clues as to why the second one behaved as it did.


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list