[Tutor] Oops concepts class vs methods.

mhysnm1964 at gmail.com mhysnm1964 at gmail.com
Thu Apr 20 07:28:35 EDT 2023


Alan,

Thanks I will refer to your tutorial again. 


I will go away and try and answer your last couple of questions and respond
tomorrow.

Sean 
-----Original Message-----
From: Tutor <tutor-bounces+mhysnm1964=gmail.com at python.org> On Behalf Of
Alan Gauld via Tutor
Sent: Thursday, April 20, 2023 8:43 PM
To: tutor at python.org
Subject: Re: [Tutor] Oops concepts class vs methods.

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



_______________________________________________
Tutor maillist  -  Tutor at python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor



More information about the Tutor mailing list