Re: [Tutor] class question

2011-01-26 Thread ALAN GAULD


> >>I'm not sure I follow that  bit.
> 
> Say you have a master part, # 3245671, this is sort of a "primary  machined 
>number".  
>
> On the blueprint for this part, there will be certain  features that don't 
> have 
>any dimensional 
>
> information, but instead have a callout  of some kind, i.e., "Hole D", or 
>somesuch.  
>
> At the top of the blueprint is  a "tab block" that is a table of "alternate 
>part numbers", 
>

Ah OK, Yes I've seen that used in produccing similar but different printed 
circuit boards
(my background is in electronics not foundry work)

> This was originally a convenience/cost saving thing, I  suspect.  

Almost certainly, and it makes it much easier to add new variants since only 
the tab values need changing.

What it means for you is that you need in parallel to your main app a 
mechanism for managing the identities through these differeing ID values.
Effectively a lookup table and mechanism for tracing designs from raw 
pattern to finished item.

> >>You may also find it useful to think through the state  model for your 
> castings/workpieces. That may help to constrain the number of  
>Actions/operations required.
> 
> ummm...what's a "state model"?  

It defines what operations can be done on your objects at any given time 
depending on the "state" of the object. As a simple example a light can 
be switched on when it is off and off when it is on, but it cannot be 
switched off if it is already off. In your can you will have a sequence of 
operations with dependencies between them such that certain operations 
can only be done after others have completed. Others cannot be done 
after others have been done. State models can be table driven which 
makes them highly configurable so that a single object can be loaded by 
multiple state models and effectively act like different object types without 
having to change the code.

HTH,

Alan G.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Steven D'Aprano

Elwin Estle wrote:

--- On Wed, 1/26/11, Alan Gauld  wrote:

From: Alan Gauld 
Subject: Re: [Tutor] class question
To: tutor@python.org
Date: Wednesday, January 26, 2011, 1:10 PM

Is this really a series of different types of casting or a single Workpiece 
going through a sequence of Actions
each Action having a set of quality data associated?



If so it may be that you have a single Workpiece class and a relatively small 
heirarchy of Actions.


No, there are multiple castings, anywhere from smallish parts you can hold in 
the palm of your hand, up to engine blocks weighing nearly 2 tons.


Then each such casting has its own set of actions and chain of classes.

There is a process that goes from egg to chick to hen to KFC Chicken 
Nuggets, but you wouldn't write a single class to model all of those 
things. You would write a separate class for each distinct stage of the 
process, and write a process that replaces each data item with the next 
one in the series.


I think you are focused too heavily on the fact that it's the same lump 
of metal all the way through the pipeline. That's the least important 
part of the design -- you can do that with a simple record:


class Lump:
def __init__(self, id, kind):
self.id = id
self.obj = kind()

lumps = [
Lump(1, EngineBlockCasting),
Lump(2, EngineBlockCasting),
Lump(3, WidgetCasting),
Lump(4, MiniCasting),
... ]

and then later on:

lumps[1].obj = EngineBlockWithHolesDrilled()

Although of course you will write functions or methods to move from one 
class to another, e.g. drill_holes(lumps, 1), rather than do it all by hand.




--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Elwin Estle

--- On Wed, 1/26/11, Alan Gauld  wrote:

From: Alan Gauld 
Subject: Re: [Tutor] class question
To: tutor@python.org
Date: Wednesday, January 26, 2011, 1:10 PM
>>Is this really a series of different types of casting or a single Workpiece 
>>going through a sequence of Actions
>>each Action having a set of quality data associated?

>>If so it may be that you have a single Workpiece class and a relatively small 
>>heirarchy of Actions.

No, there are multiple castings, anywhere from smallish parts you can hold in 
the palm of your hand, up to engine blocks weighing nearly 2 tons.

>>Is it the casting or the machining that has the quality related data? ie Is 
>>it casting specific or operation specific?

The casting can have quality data associated with it, tho rarely.  If there is 
a machining issue that can be traced back to defective castings, then yes (but 
we don't really have any process in place for this, normally that sort of thing 
is the casting supplier's problem).  Normally, tho, it is the machining that 
has the associated quality data., i.e., measure a 2.500 machined bore with a 
+/- .001 tolerance, using such and such gage, giving some result (like 2.503, 
for example), measured on such and such date by such and such machine operator. 
 Various bits like this will be associated with a given machining operation.  
Sometimes machining operations are all done on a single machine, sometimes they 
span multiple machines.

>>Do you know in advance what these operations will be? Can you assign a 
>>WorkPlan to the Workpiece? Each step of the plan having an associated Action?

I would say yes.  However, and this ties in with something you ask further 
down, sometimes that plan may sort of "overlap"  For example, say we have a raw 
casting, 3402963R, that when machined, becomes part # 3402963.  But that same 
raw casting may also be machined into another part number # 3332965, simply by 
adding or omitting hole or some other feature.  So, I suppose one could have 
separate plans for each finished part number, in which case there might be some 
duplication of things for each plan.

> Each of those operations on separate machines will have a different set of 
> quality checks associated with it.

So here we clearly say it is the Action that has the data associated...

> ...or it might be a part that goes from a raw casting to a sort of 
> "mini-assembly" such as a rocker lever ...
> but it is still the same thing, and each one of those steps may have some 
> sort of quality check involved.

So a workpice can consist of other WorkPieces.
And again tyhe Actions associated have quality data

>>> Lets complicate things even further. One raw casting may be machined into 
>>> multiple part numbers.

>>Is that true? Or is it one type of casting?
>>Each instance of casting will surely onmly go through one specific set of 
>>actions? If we treat them all as generic >>workpieces then the Actions are 
>>different but the workpiece concept remains constant?

>>Or, are we saying that a single original workpiece can be cut into several 
>>distinct workpieces? Again thats not >>necessarily a problem, objects can 
>>clone themselves and have the clones diverge thereafter.

Yes, that is the case, as described above.

>>> This is done through something called a "tabbed" blueprint, wherein there 
>>> is a master number, but there are "tabs" indicating that if you changes 
>>> such and such feature, then the part number isn't the master number, but 
>>> the tabbed number.

>>I'm not sure I follow that bit.

Say you have a master part, # 3245671, this is sort of a "primary machined 
number".  On the blueprint for this part, there will be certain features that 
don't have any dimensional information, but instead have a callout of some 
kind, i.e., "Hole D", or somesuch.   At the top of the blueprint is a "tab 
block" that is a table of "alternate part numbers", vs these "named features".  
Each of these part numbers will have differing information as to the nature of 
"Hole D".  Perhaps the size of "Hole D" differs from one part number to the 
next, or perhaps it is omitted all together.  It goes along wth the "one 
casting makes multiple part numbers" thing described above.  In and of itself, 
this perhaps may not seem that complicated...but the blueprints aren't filed 
under the the actual part number for a given tabbed part, but under the master 
number.  So...you may have part 3458760, but the blueprint for it is filed 
under 3245671, so you have to go hunt up that
 blueprint, then hunt up the information on it that describes the actual part 
in question.  All this ties in to your qual

Re: [Tutor] class question

2011-01-26 Thread Alan Gauld


"Elwin Estle"  wrote 

The class in question, does, in fact, deal with a thing. 
The problem is, the "thing" is highly mutable. 


You can mutate objects, that is not a problem.
But you need to be sure you need to.

Is this really a series of different types of casting or 
a single Workpiece going through a sequence of Actions

each Action having a set of quality data associated?

If so it may be that you have a single Workpiece class 
and a relatively small heirarchy of Actions.


A raw casting comes into a factory. It is listed as such. 
When machined, this part number changes to a 
different part number. The raw casting has no 
"quality related" stuff, but the machined casting does, 


Is it the casting or the machining that has the quality 
related data? ie Is it casting specific or operation specific?


...because, the raw casting may go through multiple 
operations to get to it's final state. 


Do you know in advance what these operations will be? 
Can you assign a WorkPlan to the Workpiece? Each 
step of the plan having an associated Action?


Each of those operations on separate machines will 
have a different set of quality checks associated with it.


So here we clearly say it is the Action that has the 
data associated...


...or it might be a part that goes from a raw casting to 
a sort of "mini-assembly" such as a rocker lever ...
but it is still the same thing, and each one of those 
steps may have some sort of quality check involved.


So a workpice can consist of other WorkPieces.
And again tyhe Actions associated have quality data

Lets complicate things even further. One raw casting 
may be machined into multiple part numbers. 


Is that true? Or is it one type of casting?
Each instance of casting will surely onmly go through 
one specific set of actions? If we treat them all as generic 
workpieces then the Actions are different but the workpiece 
concept remains constant?


Or, are we saying that a single original workpiece can 
be cut into several distinct workpieces? Again thats 
not necessarily a problem, objects can clone themselves 
and have the clones diverge thereafter.


Perhaps the only thing that changes is the location 
of a single hole. But again, each one of those part 
numbers may go through multiple machining operations 
on different machines, with different quality checks. 


This is done through something called a "tabbed" 
blueprint, wherein there is a master number, but there 
are "tabs" indicating that if you changes such and 
such feature, then the part number isn't the master 
number, but the tabbed number.


I'm not sure I follow that bit.

So, in essence, there's a sort of "network" of "is-a" 
and "has-a" information.


I see a lot of "has-a" but very little "is-a" at this stage.
In fact I don't see any "is-a" yet, althopugh I can see 
where some might emerge in the future.


have a sort of "component aggregate" class, which 
would cover not only single parts, but assemblies 


I think that will  be essential.

if a part was as simple as a raw casting that is 
just machined into a finished part and that's it, 
it would still be treated as a sort of assembly, 


One of the key features of assemblies is that they 
should scale down to a single item just as easily 
as up to many parts.


So there's all this information associated with a 
given part. I am thinking it has a sort of tree structure. 


I think there probably is and you should look into 
the composite pattern to build that. 

I am just wondering if some of the branches of 
the tree should be separate classes 


Probably, but not so many different classes as 
you currently suspect.


...and yeah, I know, it's kind of a complex problem 
for a newbie to be thinking about.


Yes, very challenging. This is one of the kinds of 
problem where the best solution is probably not be 
the first one you think of. But you won't know that 
till after you try building it!


My proposal is only a guess based on a quick 
review of your description and no local domain 
knowledge...


You may also find it useful to think through the 
state model for your castings/workpieces. That 
may help to constrain the number of Actions/operations 
required.


--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Alan Gauld


"Karim"  wrote

Sure, but I come from java world and 1 inheritance is allowed but we 
can implement multiple interfaces.
I like to use Abstract classes in Python then inherit and implement 
abstract method like in java (at least


Sure and that is the normal way of doing it. Not least because you
can inherit non abstract methods too! But there is a danger of 
forgetting

that inheritance is not the *only* way.

Thats all I was pointing out, inheritance is the norm but not 
essential.


--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Izz ad-Din Ruhulessin
class Raw ---> class Processor ---> class Final

2011/1/26 Tino Dai 

>
>
>>
>> A raw casting comes into a factory.  It is listed as such.  When machined,
>> this part number changes to a different part number.   The raw casting has
>> no "quality related" stuff, but the machined casting does, and it can have
>> more than one "quality related" thing.
>>
>> ...because, the raw casting may go through multiple operations to get to
>> it's final state.  It may get machined on a lathe, then be transferred to a
>> CNC machining station where a bolt circle may be drilled and tapped into
>> it.  Each of those operations on separate machines will have a different set
>> of quality checks associated with it.
>>
>> ...or it might be a part that goes from a raw casting to a sort of
>> "mini-assembly" such as a rocker lever (if you know what that is), so we
>> have raw casting = one part number, then it gets a bushing pressed into it =
>> another part number, then it gets a threaded insert = another part number,
>> but it is still the same thing, and each one of those steps may have some
>> sort of quality check involved.
>>
>> Lets complicate things even further.  One raw casting may be machined into
>> multiple part numbers.  Perhaps the only thing that changes is the location
>> of a single hole.  But again, each one of those part numbers may go through
>> multiple machining operations on different machines, with different quality
>> checks.  This is done through something called a "tabbed" blueprint, wherein
>> there is a master number, but there are "tabs" indicating that if you
>> changes such and such feature, then the part number isn't the master number,
>> but the tabbed number.
>>
>> So, in essence, there's a sort of "network" of "is-a" and "has-a"
>> information.
>>
>> My idea was to, instead of having just a single "part" class, to have a
>> sort of "component aggregate" class, which would cover not only single
>> parts, but assemblies of parts.  So, even if a part was as simple as a raw
>> casting that is just machined into a finished part and that's it, it would
>> still be treated as a sort of assembly, with the raw casting being a
>> component of the finished part number, if that makes sense.
>>
>> So there's all this information associated with a given part.  I am
>> thinking it has a sort of tree structure.  I am just wondering if some of
>> the branches of the tree should be separate classes that are then tied into
>> the "trunk" of the master class, or if the whole thing should be a tree into
>> and of itself.
>>
>> ...and yeah, I know, it's kind of a complex problem for a newbie to be
>> thinking about.
>>
>>
>>
>>
> Here is my two-cents. This code is untested. Import statements haven't been
> included, there could be syntax errors, etc etc etc. What I did
> was switching off the part_number attribute in the Thing class. For the
> functions that "do stuff" to the thing instance, I appended a part-number
> (assuming new part number = master number + doing stuff number). The quality
> functions will check for that part number before proceeding with the checks.
>
>
> class Thing:   # single part class
>  def __init__(self,part_number='12345'):   # 12345 is a default
> part number
>   self.part_number=part_number
>
> def routeThing(thing):
>  try:
>  thing.part_number.append('-someRoutingPartNumber')
>  
>  exception AttributeError (e):
>   e.printStackTrace()
>   print "Router was not applied to thing"
>
> def checkQualityRoute1(thing):
>  if hasattrib(thing,part_number) &&
> (thing.part_number.find('-someRoutingPartNumber'):
> 
>  else:
>  print "Thing has not be routed yet"
>
> def checkQualityRoute2(thing):
>  if hasattrib(thing,part_number) &&
> (thing.part_number.find('-someRoutingPartNumber'):
> 
>  else:
>  print "Thing has not be routed yet"
>
>  continue for all of the functions that you might need
>
> HTH,
> -Tino
>
>
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Tino Dai
>
>
> A raw casting comes into a factory.  It is listed as such.  When machined,
> this part number changes to a different part number.   The raw casting has
> no "quality related" stuff, but the machined casting does, and it can have
> more than one "quality related" thing.
>
> ...because, the raw casting may go through multiple operations to get to
> it's final state.  It may get machined on a lathe, then be transferred to a
> CNC machining station where a bolt circle may be drilled and tapped into
> it.  Each of those operations on separate machines will have a different set
> of quality checks associated with it.
>
> ...or it might be a part that goes from a raw casting to a sort of
> "mini-assembly" such as a rocker lever (if you know what that is), so we
> have raw casting = one part number, then it gets a bushing pressed into it =
> another part number, then it gets a threaded insert = another part number,
> but it is still the same thing, and each one of those steps may have some
> sort of quality check involved.
>
> Lets complicate things even further.  One raw casting may be machined into
> multiple part numbers.  Perhaps the only thing that changes is the location
> of a single hole.  But again, each one of those part numbers may go through
> multiple machining operations on different machines, with different quality
> checks.  This is done through something called a "tabbed" blueprint, wherein
> there is a master number, but there are "tabs" indicating that if you
> changes such and such feature, then the part number isn't the master number,
> but the tabbed number.
>
> So, in essence, there's a sort of "network" of "is-a" and "has-a"
> information.
>
> My idea was to, instead of having just a single "part" class, to have a
> sort of "component aggregate" class, which would cover not only single
> parts, but assemblies of parts.  So, even if a part was as simple as a raw
> casting that is just machined into a finished part and that's it, it would
> still be treated as a sort of assembly, with the raw casting being a
> component of the finished part number, if that makes sense.
>
> So there's all this information associated with a given part.  I am
> thinking it has a sort of tree structure.  I am just wondering if some of
> the branches of the tree should be separate classes that are then tied into
> the "trunk" of the master class, or if the whole thing should be a tree into
> and of itself.
>
> ...and yeah, I know, it's kind of a complex problem for a newbie to be
> thinking about.
>
>
>
>
Here is my two-cents. This code is untested. Import statements haven't been
included, there could be syntax errors, etc etc etc. What I did
was switching off the part_number attribute in the Thing class. For the
functions that "do stuff" to the thing instance, I appended a part-number
(assuming new part number = master number + doing stuff number). The quality
functions will check for that part number before proceeding with the checks.


class Thing:   # single part class
 def __init__(self,part_number='12345'):   # 12345 is a default part
number
  self.part_number=part_number

def routeThing(thing):
 try:
 thing.part_number.append('-someRoutingPartNumber')
 
 exception AttributeError (e):
  e.printStackTrace()
  print "Router was not applied to thing"

def checkQualityRoute1(thing):
 if hasattrib(thing,part_number) &&
(thing.part_number.find('-someRoutingPartNumber'):

 else:
 print "Thing has not be routed yet"

def checkQualityRoute2(thing):
 if hasattrib(thing,part_number) &&
(thing.part_number.find('-someRoutingPartNumber'):

 else:
 print "Thing has not be routed yet"

 continue for all of the functions that you might need

HTH,
-Tino
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Elwin Estle
Elwin Estle wrote:

> Is it better to have one large sort of "do it all" class, or break
> the larger class up into smaller classes?

Yes.

Or no.

It's impossible to answer that question definitively without knowing more about 
what "it all" is. But I can give some general advice:

* Python isn't Java. Don't feel that you must use classes. If your problem is 
better solved using a procedural or functional approach, go right ahead and use 
it. Classes aren't compulsory.

* The standard model which you should use it:

  verbs -> functions or methods
  nouns -> classes or attributes

  You should be able to answer the question "What *thing* does
  your class represent?". (The answer can be an abstract thing,
  but it should be a thing.)

  If you can't answer that question, then you shouldn't use a
  class. You should solve the problem using stand-alone functions.

* Think about "is-a" and "has-a" relationships:
==

The class in question, does, in fact, deal with a thing.  The problem is, the 
"thing" is highly mutable.   The "is-a" and the "has-a" changes.

Here is the scenario:

A raw casting comes into a factory.  It is listed as such.  When machined, this 
part number changes to a different part number.   The raw casting has no 
"quality related" stuff, but the machined casting does, and it can have more 
than one "quality related" thing.

...because, the raw casting may go through multiple operations to get to it's 
final state.  It may get machined on a lathe, then be transferred to a CNC 
machining station where a bolt circle may be drilled and tapped into it.  Each 
of those operations on separate machines will have a different set of quality 
checks associated with it.

...or it might be a part that goes from a raw casting to a sort of 
"mini-assembly" such as a rocker lever (if you know what that is), so we have 
raw casting = one part number, then it gets a bushing pressed into it = another 
part number, then it gets a threaded insert = another part number, but it is 
still the same thing, and each one of those steps may have some sort of quality 
check involved.

Lets complicate things even further.  One raw casting may be machined into 
multiple part numbers.  Perhaps the only thing that changes is the location of 
a single hole.  But again, each one of those part numbers may go through 
multiple machining operations on different machines, with different quality 
checks.  This is done through something called a "tabbed" blueprint, wherein 
there is a master number, but there are "tabs" indicating that if you changes 
such and such feature, then the part number isn't the master number, but the 
tabbed number.

So, in essence, there's a sort of "network" of "is-a" and "has-a" information.

My idea was to, instead of having just a single "part" class, to have a sort of 
"component aggregate" class, which would cover not only single parts, but 
assemblies of parts.  So, even if a part was as simple as a raw casting that is 
just machined into a finished part and that's it, it would still be treated as 
a sort of assembly, with the raw casting being a component of the finished part 
number, if that makes sense.

So there's all this information associated with a given part.  I am thinking it 
has a sort of tree structure.  I am just wondering if some of the branches of 
the tree should be separate classes that are then tied into the "trunk" of the 
master class, or if the whole thing should be a tree into and of itself.

...and yeah, I know, it's kind of a complex problem for a newbie to be thinking 
about.






  ___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Karim


I know the the law of Murphy.
But this one is a must-have.:-)

Regards
Karim

* One way to reduce coupling is with the Law of Demeter: if you want 
your dog to walk, don't talk to your dog's legs. You will only confuse 
the dog and it won't get anywhere.


http://en.wikipedia.org/wiki/Law_of_Demeter



Hope this helps.





___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Karim


Sure, but I come from java world and 1 inheritance is allowed but we can 
implement multiple interfaces.
I like to use Abstract classes in Python then inherit and implement 
abstract method like in java (at least

that's all I remember from Java experience).
Indeed I was too direct everybody has the same style.

Regards
Karim

On 01/26/2011 12:08 PM, Alan Gauld wrote:


"Karim"  wrote


Program towards interface that means you have to use inheritance.


Just to be picky, you can program by interface without using 
inheritance. Inheritance is only needed to implement interfaces in 
languages like C++. In Python (and other dynamically bound OOP 
languages) you can use polymorphism without inheritance.




___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-26 Thread Alan Gauld


"Karim"  wrote


Program towards interface that means you have to use inheritance.


Just to be picky, you can program by interface without using 
inheritance. Inheritance is only needed to implement interfaces 
in languages like C++. In Python (and other dynamically 
bound OOP languages) you can use polymorphism without 
inheritance.


--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Corey Richardson
On 01/25/2011 08:50 PM, Steven D'Aprano wrote:
> Corey Richardson wrote:
>> On 01/25/2011 06:26 PM, Elwin Estle wrote:
>>> Is it better to have one large sort of "do it all" class, or break
>>> the larger class up into smaller classes?
> 
>> If you're just learning, go ahead and make a 'do it all' class. Don't do
>> it later in your growth as a programmer though.
> 
> Learn bad habits first, then spend years trying to break them!
> 
> *wink*


Hey, gotta learn the concepts first, right? ;-)
I remember my first "substantial" program, hangman! Quite a mess.
Excerpt:

def getlist3(self):
list3 = []
for i in range(5):
list3.append(self.gameWord[i])
self.list3 = list3

I don't even remember what list3 is. I have a whole function for a list
comprehension!

self.list3 = [char for (idx, char) in enumerate(gameWord) if
  gameWord.index(char, idx) < 5]

(list3 happened to be the hint characters given, remembered while doing)

Just proof that it doesn't have to take years, it could take months.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Steven D'Aprano

Corey Richardson wrote:

On 01/25/2011 06:26 PM, Elwin Estle wrote:

Is it better to have one large sort of "do it all" class, or break the larger 
class up into smaller classes?



If you're just learning, go ahead and make a 'do it all' class. Don't do
it later in your growth as a programmer though.


Learn bad habits first, then spend years trying to break them!

*wink*



--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Steven D'Aprano

Elwin Estle wrote:


Is it better to have one large sort of "do it all" class, or break
the larger class up into smaller classes?


Yes.

Or no.

It's impossible to answer that question definitively without knowing 
more about what "it all" is. But I can give some general advice:


* Python isn't Java. Don't feel that you must use classes. If your 
problem is better solved using a procedural or functional approach, go 
right ahead and use it. Classes aren't compulsory.


* The standard model which you should use it:

  verbs -> functions or methods
  nouns -> classes or attributes

  You should be able to answer the question "What *thing* does
  your class represent?". (The answer can be an abstract thing,
  but it should be a thing.)

  If you can't answer that question, then you shouldn't use a
  class. You should solve the problem using stand-alone functions.

* Think about "is-a" and "has-a" relationships:

  - if x is a Foo, then use a class Foo and make x an instance of Foo
  - if x has a Foo, then give x an attribute x.foo which is a Foo


* Classes should represent a *single* well-defined thing. That might be 
a compound thing, or a collection of things -- the class represents the 
entire collection. If the thing is made of parts, each part could be 
represented by an attribute. This is okay:


class Coffee:
def __init__(self):
self.style = 'white'
self.milk = 'full cream'
self.sugars = 1
self.size = 'regular'

class Pie:
def __init__(self):
self.kind = 'cherry'
self.slices = 1
self.with_cream = False

class SpecialOfTheDay:
def __init__(self):
self.drink = Coffee()
self.snack = Pie()

But don't design a class like this:

class CoffeeAndPie:
def __init__(self):
self.style = 'white'
self.milk = 'full cream'
self.sugars = 1
self.size = 'regular'
self.kind = 'cherry'
self.slices = 1
self.with_cream = False

One slice of coffee? Oh really?


* Classes should be more general rather than too specific. But don't go 
crazy and make it so abstract that you run out of air to breathe, and 
nobody can understand what the hell the class is for:


http://www.joelonsoftware.com/articles/fog18.html

* Coupling is usually bad. Aim to reduce coupling, unless you have a 
good reason for wanting strongly coupled systems. What's coupling? A key 
and a lock are *highly* coupled: only one key will fit the lock, and no 
other key will do the job. But, say, a knife and a steak are loosely 
coupled. Any sharp knife will cut a steak. Sure, some knives are better 
than others, but at a pitch, you could even use a blunt butter-knife and 
a lot of effort. Another example: your clothes iron and ironing board 
have very loose coupling. You can use any iron on any board, and it will 
be just fine. But the memory cards in your computer are moderately 
coupled with the motherboard: only some memory cards will fit. You can't 
use a 1980 64K memory card in a 2011 motherboard. But provided the 
memory will fit, it doesn't matter which card you use.


* One way to reduce coupling is with the Law of Demeter: if you want 
your dog to walk, don't talk to your dog's legs. You will only confuse 
the dog and it won't get anywhere.


http://en.wikipedia.org/wiki/Law_of_Demeter



Hope this helps.



--
Steven

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Karim


Hello,

Design Patterns is the key for code reuse and problem solving. Indeed 
you have to separate your objects (classes) to use
it. The god class is like a script with only one function: not very 
flexible and easy to debug.

Program towards interface that means you have to use inheritance.
Try to determine the objects you need for your problem and next step is 
how arrange it together (relational).


Regards
Karim


On 01/26/2011 01:28 AM, Marc Tompkins wrote:

On Tue, Jan 25, 2011 at 3:26 PM, Elwin Estle  wrote:

Is it better to have one large sort of "do it all" class, or break the larger class up 
into smaller classes?  Seems to me like the one large class would be clearer in some ways.  I have 
something I am trying to do that have somewhere in the neighborhood of 20 attributes that all 
relate together, however there are sort of "clumps" of attributes that have a 
sub-relationship to each other and I wondered if they should be their own class, but I am not sure, 
assuming that is a good idea, how these smaller classes might work together.  I have only the 
foggiest notion of inheritance and I'd kind of like to stay away from that aspect of things until I 
get a better grasp of individual classes.


For me, the question of one big class/multiple smaller classes comes
down to reusability.
If you find yourself writing the same code over and over again (or
cutting/pasting big blocks of code), you should probably break up your
classes.

--
www.fsrtechnologies.com
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Alan Gauld
"Elwin Estle"  wrote 

Is it better to have one large sort of "do it all" class, 
or break the larger class up into smaller classes? 


Usually the latter. But remember that classes model objects.
Objects usually have a direct relationship to some kind of 
"real world" entity - even if its an abstract conceptual entity.


So if the attributes and behaviours are all exhibited by the 
thing you are modelling then they should maybe stay together.
But uasually the big thing can be modelled as a composition 
of smaller things...


Seems to me like the one large class would be clearer 
in some ways. 


Very rarely is a big lump of code clearer than several small
single purpose lumps of code. And big lumps of code are 
nearly always harder to reuse - one of the other reasons 
to create classes...


I have something I am trying to do that have somewhere 
in the neighborhood of 20 attributes that all relate together, 
however there are sort of "clumps" of attributes that have 
a sub-relationship to each other 


Without specifics we can't be sure. But it sounds like you 
have a composite structure. OTOH 20 attributes is not 
enormous - 200 would be, but not 20. But even 20 is enough 
to challenge.


I have only the foggiest notion of inheritance 


It doesn't sound like inheritance is an issue here. It sounds 
like we are talking about composition. But without specific 
details we can't be sure.


Remember that the thing that defines a class should be 
its operations not its data. Do these smaller "clumps of attributes" 
have common behaviour associated with them? The data 
should only be there to support the operations.


HTH,

--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Marc Tompkins
On Tue, Jan 25, 2011 at 3:26 PM, Elwin Estle  wrote:
>
> Is it better to have one large sort of "do it all" class, or break the larger 
> class up into smaller classes?  Seems to me like the one large class would be 
> clearer in some ways.  I have something I am trying to do that have somewhere 
> in the neighborhood of 20 attributes that all relate together, however there 
> are sort of "clumps" of attributes that have a sub-relationship to each other 
> and I wondered if they should be their own class, but I am not sure, assuming 
> that is a good idea, how these smaller classes might work together.  I have 
> only the foggiest notion of inheritance and I'd kind of like to stay away 
> from that aspect of things until I get a better grasp of individual classes.
>

For me, the question of one big class/multiple smaller classes comes
down to reusability.
If you find yourself writing the same code over and over again (or
cutting/pasting big blocks of code), you should probably break up your
classes.

--
www.fsrtechnologies.com
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2011-01-25 Thread Corey Richardson
On 01/25/2011 06:26 PM, Elwin Estle wrote:
> Is it better to have one large sort of "do it all" class, or break the larger 
> class up into smaller classes?  Seems to me like the one large class would be 
> clearer in some ways.  I have something I am trying to do that have somewhere 
> in the neighborhood of 20 attributes that all relate together, however there 
> are sort of "clumps" of attributes that have a sub-relationship to each other 
> and I wondered if they should be their own class, but I am not sure, assuming 
> that is a good idea, how these smaller classes might work together.  I have 
> only the foggiest notion of inheritance and I'd kind of like to stay away 
> from that aspect of things until I get a better grasp of individual classes.
> 

If you're just learning, go ahead and make a 'do it all' class. Don't do
it later in your growth as a programmer though.

Inheritance works like this:

class Parent:
def __init__(self):
print "Parent initialised"

class Child(Parent):
pass

The parenthesis set the superclass or parent class. If you now do:

c = Child()

You should see "Parent initialised" printed to the terminal. It makes
all the 'parents' methods available to it. You can think of it as
copying all the code from the parent class into the child class. You can
overwrite the methods too:

class Animal:
def speak(self):
print self.noise

class Pig(Animal):
def __init__(self):
self.noise = "Oink!"

pig = Pig()
pig.speak()

Hope it helped,
~Corey
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Tiger12506
Ooops, didn't see Alan's post before I sent this...

JS

>> Your second way seems to make more sense. And instead of raising the
>> error, why not just print it:
>
> There is a very good reason for this and it's important that you 
> understand
> it to write good code. If you use a print statement, you break the benefit
> of encapsulation.
>
> If you were to use that class in a GUI application, for example, you would
> never know if the account had become overdrawn. Only by using an exception
> could you use that class effectively in both circumstances, and in the 
> same
> way!
>
> a = BankAccount()
> try:
>  a.withdraw(50)
> except:
>  notify_error()
>
> Where notify error depends on how you want to communicate that information
> to the end-user. (messagebox, display, stdout, stderr, file, etc)
>
> JS

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Dick Moores
At 03:12 PM 7/13/2007, Alan Gauld wrote:

>"Dick Moores" <[EMAIL PROTECTED]> wrote
>
> > Thanks. You've clarified it for me completely.
> >
> > Your second way seems to make more sense.
> > And instead of raising the error, why not just print it:
>
>Because that would make the class much less reusable.
>It would be limited to applications using stdout. A GUI
>banking program would be unable to use the BankAccount
>class. But by raising an exception the user gets to decide
>what to do, either pop up a dialog, print a message or send
>an email to the banks client.
>
>Its a primary design goal for reuse to de-couple business
>logic - like the bank account - from the user interface.
>
>There is a bit more discussion around this in my
>Case Study topic where I convert it from command
>line to GUI and again in my InterProcess Comms topic
>where I turn the AddressBook into a client-server app.

Thanks, Alan. I'll check it out.

Dick


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Tiger12506
> Your second way seems to make more sense. And instead of raising the 
> error, why not just print it:

There is a very good reason for this and it's important that you understand 
it to write good code. If you use a print statement, you break the benefit 
of encapsulation.

If you were to use that class in a GUI application, for example, you would 
never know if the account had become overdrawn. Only by using an exception 
could you use that class effectively in both circumstances, and in the same 
way!

a = BankAccount()
try:
  a.withdraw(50)
except:
  notify_error()

Where notify error depends on how you want to communicate that information 
to the end-user. (messagebox, display, stdout, stderr, file, etc)

JS 

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Alan Gauld

"Dick Moores" <[EMAIL PROTECTED]> wrote 

> Thanks. You've clarified it for me completely. 
> 
> Your second way seems to make more sense. 
> And instead of raising the error, why not just print it:

Because that would make the class much less reusable. 
It would be limited to applications using stdout. A GUI 
banking program would be unable to use the BankAccount 
class. But by raising an exception the user gets to decide 
what to do, either pop up a dialog, print a message or send 
an email to the banks client.

Its a primary design goal for reuse to de-couple business 
logic - like the bank account - from the user interface.

There is a bit more discussion around this in my 
Case Study topic where I convert it from command 
line to GUI and again in my InterProcess Comms topic 
where I turn the AddressBook into a client-server app.


HTH,

-- 
Alan Gauld
Author of the Learn to Program web site
http://www.freenetpages.co.uk/hp/alan.gauld


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Dick Moores


At 12:35 PM 7/13/2007, [EMAIL PROTECTED] wrote:
However if you try to withdraw
any money after you took out the $25 it would raise the error. 
The overdrawn function checks if you are in the negatives. 
Since the balance is checked before the money is taken out, there is no
error when you take out the $25. 
If you wan the error to be raised whenever you go negative simply switch
the withdrawal and the function call in withdraw 
 def withdraw(self, amount): 
    self.balance -=
amount
   if self.overdrawn():
  raise
"Insufficient Funds Error"

and if you don't want the money taken out if there is insufficient
funds, 
just add the withdrawn amount back: 
 def withdraw(self, amount): 
    self.balance -=
amount
   if self.overdrawn(): 
    self.balance +=
amount
  raise
"Insufficient Funds Error, no money withdrawn" 

Thanks. You've clarified it for me completely. 
Your second way seems to make more sense. And instead of raising the
error, why not just print it:
class BankAccount(object):
   def __init__(self, initial_balance=0):
   self.balance = initial_balance
   def deposit(self, amount):
   self.balance += amount
   def withdraw(self, amount): 
   self.balance -= amount
   if self.overdrawn(): 
   self.balance
+= amount
   print
"Insufficient Funds, no money withdrawn"   

   def overdrawn(self):
   return self.balance < 0
my_account = BankAccount(15)
my_account.withdraw(25)
print "Account balance is", my_account.balance
Dick



___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread christopher . henk
However if you try to withdraw any money after you took out the $25 it 
would raise the error.

The overdrawn function checks if you are in the negatives.
Since the balance is checked before the money is taken out, there is no 
error when you take out the $25.

If you wan the error to be raised whenever you go negative simply switch 
the withdrawal and the function call in withdraw

 def withdraw(self, amount):
self.balance -= amount
if self.overdrawn():
   raise "Insufficient Funds Error"

and if you don't want the money taken out if there is insufficient funds,
just add the withdrawn amount back:

 def withdraw(self, amount):
self.balance -= amount
if self.overdrawn():
self.balance += amount
   raise "Insufficient Funds Error, no money withdrawn"

 Chris Henk
Allison Transmission
phone:  317.242.2569
fax:  317.242.3469
e-mail:  [EMAIL PROTECTED]



Dick Moores <[EMAIL PROTECTED]> 
Sent by: [EMAIL PROTECTED]
07/13/2007 03:04 PM

To
Tiger12506 <[EMAIL PROTECTED]>, 
cc

Subject
Re: [Tutor] class question






At 05:35 AM 7/13/2007, Tiger12506 wrote:
> > ===
> > class BankAccount(object):
> >def __init__(self, initial_balance=0):
> >self.balance = initial_balance
> >def deposit(self, amount):
> >self.balance += amount
> >def withdraw(self, amount):
> >self.balance -= amount
> >def overdrawn(self):
> >return self.balance < 0
> > my_account = BankAccount(15)
> > my_account.withdraw(5)
> > print my_account.balance
> > =
> >
> > This prints the expected "10".
> >
> > My question is, of what use can "overdrawn" be put? If I change the
> > withdrawal amount to 25, it prints the expected "-10", whether the 
class
> > contains the "overdrawn" function or not.
> >
> > Thanks,
> >
> > Dick Moores
>
>A very good question. Now I have one for you. What does your bank do when
>you try to withdraw money? First, it checks to see if you have the money 
in
>your account. If you do, it subtracts that out of your balance. Whoever
>wrote that code failed to do the check within the withdraw function.
>
>===
>class BankAccount(object):
>def __init__(self, initial_balance=0):
>self.balance = initial_balance
>def deposit(self, amount):
>self.balance += amount
>def withdraw(self, amount):
>if self.overdrawn():
>   raise "Insufficient Funds Error"
>self.balance -= amount
>def overdrawn(self):
>return self.balance < 0
>my_account = BankAccount(15)
>my_account.withdraw(5)
>print my_account.balance
>=

But when I run that with a withdrawal of 25, it still prints only 
"-10". How have you involved the "overdrawn" function?

Dick


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Dick Moores
At 05:35 AM 7/13/2007, Tiger12506 wrote:
> > ===
> > class BankAccount(object):
> >def __init__(self, initial_balance=0):
> >self.balance = initial_balance
> >def deposit(self, amount):
> >self.balance += amount
> >def withdraw(self, amount):
> >self.balance -= amount
> >def overdrawn(self):
> >return self.balance < 0
> > my_account = BankAccount(15)
> > my_account.withdraw(5)
> > print my_account.balance
> > =
> >
> > This prints the expected "10".
> >
> > My question is, of what use can "overdrawn" be put? If I change the
> > withdrawal amount to 25, it prints the expected "-10", whether the class
> > contains the "overdrawn" function or not.
> >
> > Thanks,
> >
> > Dick Moores
>
>A very good question. Now I have one for you. What does your bank do when
>you try to withdraw money? First, it checks to see if you have the money in
>your account. If you do, it subtracts that out of your balance. Whoever
>wrote that code failed to do the check within the withdraw function.
>
>===
>class BankAccount(object):
>def __init__(self, initial_balance=0):
>self.balance = initial_balance
>def deposit(self, amount):
>self.balance += amount
>def withdraw(self, amount):
>if self.overdrawn():
>   raise "Insufficient Funds Error"
>self.balance -= amount
>def overdrawn(self):
>return self.balance < 0
>my_account = BankAccount(15)
>my_account.withdraw(5)
>print my_account.balance
>=

But when I run that with a withdrawal of 25, it still prints only 
"-10". How have you involved the "overdrawn" function?

Dick


___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] class question

2007-07-13 Thread Tiger12506
> ===
> class BankAccount(object):
>def __init__(self, initial_balance=0):
>self.balance = initial_balance
>def deposit(self, amount):
>self.balance += amount
>def withdraw(self, amount):
>self.balance -= amount
>def overdrawn(self):
>return self.balance < 0
> my_account = BankAccount(15)
> my_account.withdraw(5)
> print my_account.balance
> =
>
> This prints the expected "10".
>
> My question is, of what use can "overdrawn" be put? If I change the 
> withdrawal amount to 25, it prints the expected "-10", whether the class 
> contains the "overdrawn" function or not.
>
> Thanks,
>
> Dick Moores

A very good question. Now I have one for you. What does your bank do when 
you try to withdraw money? First, it checks to see if you have the money in 
your account. If you do, it subtracts that out of your balance. Whoever 
wrote that code failed to do the check within the withdraw function.

===
class BankAccount(object):
   def __init__(self, initial_balance=0):
   self.balance = initial_balance
   def deposit(self, amount):
   self.balance += amount
   def withdraw(self, amount):
   if self.overdrawn():
  raise "Insufficient Funds Error"
   self.balance -= amount
   def overdrawn(self):
   return self.balance < 0
my_account = BankAccount(15)
my_account.withdraw(5)
print my_account.balance
=

JS 

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor