[Tutor] Oops concepts class vs methods.

Alan Gauld alan.gauld at yahoo.co.uk
Thu Apr 20 06:42:50 EDT 2023


On 20/04/2023 10:05, mhysnm1964 at gmail.com wrote:

> In the past I sent some code through related to WX python that I am working
> on to see if I can make an accessible home book-shelf library program. Thus
> the reasons for these OOPS questions. I am trying to work out if I should
> create the following code as a generic method or class. My simplistic
> understanding of Oops. 
> 
> *	A class is an object such as creating a GUI window.

A class represents an object. It is a pattern for an object. The object
is the instance that you create from the class. (Although to confuse
things, in Python(and a few other languages) classes are objects too!)

Keeping the distinction between classes and objects clear in your
mind is critical to success in OOP.

> *	Method is the action you want to do Such as creating an edit control
> or performing a database query.

Strictly speaking a method is a response to a message. Each object
responds to the same message using a different method. The method
definition looks a lot like a function in a non OOP context. And a
message looks a lot like a function call...

> *	Properties are the variables of the class / method.

Again being pedantic the properties of a class are both its
attributes(public internal data) and its (public) methods.
ie the properties of a class are the features that it
exposes to the outside world.

But again, slightly confusingly, Python properties tend
to be used as a way to hide attributes behind methods so
that you cannot access the internal data directly but must
go through a method. (This is sometimes useful to ensure
data stays valid - eg. within certain ranges)

> I have a range of WX methods that creates a control on the panel or window.
> For example:

> class RecordPanel(wx.Panel):
> 
>     def __init__(self, parent, app):
>         wx.Panel.__init__(self, parent=parent)
> 
>         # defining the book object.
>         self.book = None
> 
>         # Create the controls for the panel
>         # adding controls to a sizer.
>         #sizer = wx.BoxSizer(wx.VERTICAL)
>         sizer = wx.FlexGridSizer(rows=0, cols=2, vgap=10, hgap=10)
>         self.title_label = wx.StaticText(self, label="Title:")
>         self.title_text = wx.TextCtrl(self, size=(300, -1))
>         sizer.Add(self.title_label, flag=wx.ALIGN_LEFT)
>         sizer.Add(self.title_text, flag=wx.EXPAND)
>         sizer.Add(wx.StaticText(self, label="About Authors:"),
>                   flag=wx.ALIGN_LEFT)
>         self.about_author_text = wx.TextCtrl(self, size=(300, 100),
> style=wx.TE_MULTILINE)
>         sizer.Add(self.about_author_text, flag=wx.EXPAND)
> 
>         # Set the publisher field
>         self.publisher_label = wx.StaticText(self, label="Publisher:")
>         self.publisher_text = wx.TextCtrl(self, size=(300, -1))
>         sizer.Add(self.publisher_label, flag=wx.ALIGN_LEFT)
>         sizer.Add(self.publisher_text, flag=wx.EXPAND)
> 
>         # Set the series field
>         self.series_label = wx.StaticText(self, label="Series:")
>         self.series_text = wx.TextCtrl(self, size=(300, -1))
>         sizer.Add(self.series_label, flag=wx.ALIGN_LEFT)
>         sizer.Add(self.series_text, flag=wx.EXPAND)
> 
> . more declaring of controls and events to be added to the page.
> 
> self.SetSizer(sizer) # applies the controls to the page.

> AS you can tell, the creation of the edit fields and the list boxes use the
> same syntax with different variables. Is it possible to create a class with
> a couple of methods to reduce the lines above to simplify the debugging and
> readability of the code? 

Sure, creating "helper methods" is standard practice. For example in an
application class you might have a buildGUI() method that gets called
from inside __init__(). Within buildGUI() you could call addLabels()
or addControls() etc...

Remember that any time you create an attribute with

self.xxxx = ....

you are making self.xxx available to all methods of the
class, including the other helper methods as well as the
top level "operational" methods. (In languages other than
Python these helper methods would typically be private
 - ie only usable by other methods of the class. But
Python doesn't support private so we use a convention
to prefix them with a double underscore:

class SomeWidget(Widget):
    def __init__(self,...):
        ...
        self.__buildGUI()
        ...
    def __buildGUI(self...):
        ...

It's purely convention and I mention it just in case you
come across it and wonder why...


> Class WindowControls(sizer, Label, label_flags, control_flags, xPosition,
> yPosition):
> 
>     # sizer is the wx sizer object 
>     # label - the label to be used for the control
>     # label_flags - the flags used to style and align the control.
>     # control_flags - flag parameters for the control.
>     # xPosition and yPosition - the size of the control.
> 
>     Def EditControl(self)
>         self.control_label = wx.StaticText(self, label=f"{label}:")
>         self.control_text = wx.TextCtrl(self, size=(xPosition, yPosition))
>         sizer.Add(self.control_label, flag=flags)
>         sizer.Add(self.title_text, flag=control_flags)
>         return sizer 

Where is the sizer defined? Should it be

return self.sizer?


My other question is about the naming of the class.
It feels a bit generic. What "window controls"?
It contains a sizer and labels so maybe it should be
called a LabeledSizer?

What kind of object is this class supposed to create?
What is it for?
Objects should have a purpose not just be a container
that you dump stuff into.
In OOP parlance you should be able to write down:

- The *Class* name
- The class *Responsibilities* (what does it do, what does it know)
- and the class's *Collaborators* (what dependencies does it have)

on a CRC card (originally a 5x3 piece of cardboard but often an
electronic note today!)

If you can't do that consider whether you should really be
making a class at all, maybe it should just be a function?

Another factor to consider is how many instances of this
class will there be? Can there be more than one? Good!
If it's only ever a singleton maybe it should be a module
instead?

> I hope the above makes sense. As I really an unsure if I am on the right
> path here or using Oops in the right way. As I do get confused when to use
> the "self" instance. 

self refers to the current object. When you are inside a method.
If you need to refer to, or modify, anything else inside the object
(inside yourself) you use self. Remember that methods react to
messages sent to instances. If you are accessing something specific
to the same object(a method or attribute) you need to use self.

For a slightly longer explanation of self see the OOP topic
in my tutorial.

-- 
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