[Tutor] Concept related to python classes

Alan Gauld alan.gauld at yahoo.co.uk
Mon Sep 7 19:54:57 EDT 2020


On 07/09/2020 22:56, boB Stepp wrote:

> And reflecting on this I suppose one might explicitly call __new__ without
> triggering __init__?

I'm not 100% sure about this but i think new conventionally
calls init. ie new creates the new object then calls init on it.
So it could be the case that if you override new and don't
call init from new then you could indeed create objects with
no init. However I have a sneaky suspicion that the meta-programming
behind classes is more sneaky than that and the init has to
get called 9things to do with building the object/class
heirarchy and initialising superclasses etc...)

Good practices says you can call init as often as you
like but new should only be called once per object and assume
that it calls init the first time.

> Self-messaging seems natural and intuitive to me.  However, when objects of
> one class need to interact with objects of another class, then this is
> where I struggle with implementation details. 

This is where most folks migrating from procedural thinking struggle
because you have to get out of the idea of thinking about the
program as a hierarchy of function calls. And that's difficult
to do, especially for anyone raised on traditional math,
since that's how we are trained to think.

> class managing the UI. 

classes should not in general manage other classes.
classes should manage themselves.
So you may have a UI class that has some components.
And those components may have subcomponents and respond
to messages and perform functions etc.
So the UI object will initiate some action (possibly as
a result from a user action) by sending messages to its
component objects. The UI object is also often called
the Application or MainWindow object. They are all terms
for the same concept. Its the thing that knows the
"rules" about what the application is supposed to do....

>  The user clicks a "Start Program" button.  

Which results on a callback function being called - and
that is likely to e a method of the UI/Window/Application object.
(Or in OOP parlance the button sends a message to its
controller, which will be the UI/Window/Application)

> user is supposed to be presented with a math problem which shows up as a
> label.  

Presumably these problems are stored as a list of Problem objects
somewhere in the Application object? The button handler selects one and
send a message to the Label to display it. (So we have a Window object
sending a Problem object to a label object. The label on receiving this
message will ask the Problem object to represent itself as a string.
(ie call Problem.__str__() ) and attach the result to its text
attribute(if using Tkinter say0

> In an entry widget to the right the user is supposed to enter his
> answer.  

Thats up to the user and outside your control. The Application displays
the entry and waits for a related event to call its handler..


> Each problem (of several to many) is an object of a
> problem-generating class.  Who instantiates the problems? 

Presumably the Application knows how many problems it wants to store?
(Or maybe it reads them from as database or config file at startup?)

> problem-generating class to stop sending problems to the UI?  

The Problem class should not be sending problems anywhere.
It should generate new problems on demand and the problem
consumer should be asking for them. A class that spontaneously
generates instances of itself would be a very odd thing indeed(*).
Think of a number generator that just continually created
numbers. Where would they go? The number class would need
to know about its consumer which would seriously limit
its reusability in any other project.

(*)Odd but not unknown - network event simulators being one
example I can think of. But the Network requires the creator
to connect it to something that consumes the events....
Its the OOP equivalent of a while True loop in procedural code.
Another example is a timer which generate clock tick events.
Notice the similarity? - both are event sources that replace
(or supplement) the user in a GUI environment...

> continue this, at the end of the problem solving session, say we want to
> save the date, time, type of problem solving session and the percentile
> score correct?  Say a file management class is used for this.  Who
> instantiates it?  

Again these are all application specific issues. So if the App needs
to store results it needs to instantiate a storage object(file,
database whatever) At the end of the session it sends a message
to that storage object to store the results. (Or possibly sends
several messages asking it to store one result at a time...
designers choice.)

Results are interesting because they could be part of the problem
object - it stores the answers and the collected attempted answers
(including the date/time of the attempt etc). Or Result might be a
separate class that contains a reference to the original Problem.
These mutual dependency relationships are the truly tricky bit of OOP
and there is often no correct answer, you just have to pick one.
Personally I'd go with the Problem knowing its own solution and being
able to evaluate an answer, but the actual answer (or result) being
a separate class that keeps tabs on date/time etc. we can then create an
Application level dictionary keyed by Problem that stores the list of
results for that problem.

> As you might suspect the above refers to an actual program that I wrote in
> procedural style that I am contemplating OOP-style as I plan on adding
> additional problem types (for my son) to solve.  It is these inter-class
> communications/instantiation responsibilities that mostly have me pulling
> my hair out.

It becomes more natural the more you do it until eventually its
coming up with a procedural solution that seems counter-intuitive.
But that takes a while for most folks. But you must keep asking the
question "What is each object responsible for?" You often have to
break up traditional procedures across multiple objects' methods.
Its not as simple as taking an existing function and transplanting
it into a class. If you try that you'll wind up just building
classes that mirror your existing procedural hierarchy. You'll
have lots of classes and a few objects but no OOP!


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