[Tutor] Help understanding classes

Alan Gauld alan.gauld at btinternet.com
Sat Nov 15 02:32:26 CET 2014

On 15/11/14 00:29, Bo wrote:
> help understanding classes and how they work. What is the point in OOP
> if I don’t understand classes, are classes not the heart and soul of
> OOP?

Actually not necessarily. There are OOP languages where classes
are not included or little used. Javascript is a good example but
there are others too.

However, since this is a Python list, we'll ignore those and
agree with you that you need to know about classes... :-)

> I have been trying to learn classes by practicing with Tkinter
> building GUIs.

While OOP is usually used in creating GUIs they are not the
best place to learn about classes because the GUI frameworks
(Tkinter in your case) do a fair bit of magic internally that
confuses things a little bit.

> window. I just don’t understand why it works?

Let's start with that.

> Where would the rest of my code go

That's where the GUI magic happens so the code doesn't
go where you might initially think it would! Later...

> class test(Frame):

This creates a new class called 'test' that defines a new
kind of Frame object (style note: class names are usually
capitalized so it should be called Test). This means that
you can create instances of it (objects of type Test)
using the usual Python syntax of class name followed
by () so:

myTestObject = Test()

As a subclass of Frame it inherits a lot of functionality
from the Frame class, including how to display itself on
screen, resize itself and so on. A Frame is a general
purpose GUI container (a bit like a visual list if you
like, except it can only hold GUI widgets). As such it
acts as the top level window of your application.
All other widgets and sub-frames will go into the
top level Frame.

This is an important point. In a GUI there is a top level
parent object and all other objects are children of that,
They form a tree-like data structure called the containment
tree. This tree is crucial to how GUIs interact with user
events (and how the widgets communicate internally) and is
the core of the GUI magic that I mentioned earlier.

 >      def __init__(self, parent):
 >          Frame.__init__(self, parent)
 >          self.parent = parent
 >          self.initUI()

This is the first method of the class. A method is a special
type of function that is defined inside a class and provides
the functionality (or operations) of the class. In this case
it is a special method that gets called by python when a new
object of type Test is created (this is OOP magic not GUI magic,
it happens for all classes). Its purpose is to initialize the
data variables (or attributes) of the new instance. In your
case that includes calling the Frame superclass to initialize
it then setting a local parent variable (you really shouldn't
need to do that! Frame does it for you) and then calling the
initGUI() method of the new instance (denoted by self).

 >      def initUI(self):
 >          self.parent.title(“TestApp")
 >          self.pack(fill=BOTH, expand=1)

And this is the initGUI() method which is just a helper
function like any other but, because it's inside the class
and has a self parameter is a custom method of your class.
It's not obligatory, but is quite common, to have a separate
method to initialize the GUI widgets in the window (not least
because it allows you to reset the window without
restarting the application).

In this case it sets the Window title then packs the window
into its parent. Recall the containment tree? When you create the 
instance you must pass a parent into init() and that call to pack()
will cause Tkinter to insert your new window under the parent
within the tree. In this case the parent will be the top level
Window but it could be a dialog box or a sub frame of a
larger window.

> def main():
>      root = Tk()
>      root.geometry("250x150+300+300")
>      app = test(root)
>      root.mainloop()

The main function creates a root object for your GUI using
the Tk() function (remember that containment tree?). It sets
the initial geometry(size and position) of the window then
creates an instance of your Test class passing the root object
as the parent. (The self parameter is filled in using more
OOP magic by Python. It takes the value of your new
object - app in this case.) So at this point your __init__()
method gets called as:

Test.__init__(app, root)

Once everything has been initialized the mainloop() of the
root widget is called which starts Tkinter looking for
events to process. It will send the events to the lowest level
widget it can find - your app widget in this case. But if
it cannot find an event handling function/method there it
will pass the event up the containment tree (this is the
GUI magic bit!) until it finds something that can handle it.
If the event reaches the top of the tree(root) without finding
a handler then it gets thrown away(usually).

Most GUI events in your app are picked up by Frame or root
(move, resize, close etc) so you don;t need to provide any
code yet.

Now we can look at what happens when you add widgets later.
First did that make any kind of sense? If not ask away because
it will help to get this clear before we start worrying about
widgets and event handlers and call-backs and the like.

And for the pure OOP issues try reading the OOP topic in my
tutorial because it explains it without the added complexity
of a GUI!

<shameless plug #2>
My new book "Python Projects" includes a chapter on GUIs
(covering Tklinter, Tix and ttf) and how to use them in
a layered application architecture.
</shameless plug>

Alan G
Author of the Learn to Program web site

More information about the Tutor mailing list