[Tutor] Class inheiritance question

D-Man dsh8290@rit.edu
Tue, 2 Jan 2001 15:58:12 -0500


Here's a sample interpreter session :

>>> class Parent :
...     def __init__( self ) :
...             self.val1 = 5 
...             self.set_val2()
...     def set_val2( self ) :
...             self.val2 = self.val1 + 3
... 
>>> class Child( Parent ) :
...     def __init__( self ) :
...             Parent.__init__( self )
...             self.val1 = 9
...             self.set_val2()
... 
>>> c = Child()
>>> c.val1
9
>>> c.val2
12
>>> 


This is the sort of effect you are looking for, right?

The child class must explicitly call the init function in the parent
(super) class.  Also, if any values are computed in the super class's
init based on other variables (such as 'val2' here), they must be
recomputed after the other variable has been given it's new value.
That is why I call set_val2 in the child's init.

Another difference here is that my set_val2 function doesn't return a
value, but instead sets the instance member directly.


On Tue, Jan 02, 2001 at 12:18:25PM -0600, mbc2@netdoor.com wrote:
> 
> Ok, I ran into some problems trying to redefine a variable set in the
> constructor. The problem was that I not only had variables that
> initialized my class from the database row passed to it, but I had also
> set variables in the constructor using some of the class's methods. For
> example:
> 
> class Position:
> 	def __init__ (self, dbrow):
> 		self.calenrate = .1 #this is just a constant
> 		#I decided to pass a dictionary to the class using the db
> 		#field name as the key, in order to make the program a
> 		#little more flexible.
> 		self.CURYRSAL = dbrow.get("curyrsal","unknown")
> 		self.basesalary = self.Basesalary()
> 
> 	def Basesalary (self):
> 		x = self.CURYRSAL*(1+self.calenrate)
> 		return x
> 
> I did this because there were other methods of the class which needed to
> use the basesalary number. I found that even if I redefined CURYRSAL in
> the sub class, the Basesalary method still used the old figure because it
> was being called in the constructor. For example:
> 

Just out of curiosity, is there a reason why the other methods can't
use the data member 'basesalary' instead of the function 'Basesalary' ?

> class Positionrlgn(Position):
> 	def __init__(self,dbrow):
> 		Position.__init__(self,dbrow) #Basesalary gets called now
> 		self.CURYRSAL = 100000 #Redefined CURYRSAL but it doesn't
> 					#matter because basesalary has
> 					#already been set.

As I mentioned above, you must call the 'Basesalary' function again
since when it ran self.CURYRSAL was the old value.

This would be a good reason to make 'Basesalary' a separate function
from the init function.  However, since it will set a member I don't
think it should be used by any functions except the init.

> 
> This caused me to think that it was probably best to only put initializing
> data into the constructor and not to call any of the methods in the
> contructor. So I rewrote my class that way. The problem I ran into (which
> is the same problem that caused me to call those methods in the
> constructor in the first place) is that I cannot call a method to set a
> varialbe.  For example:
> 
> def Basesalary (self):
> 	x = self.CURYRSAL*(1+self.calenrate)
> 	return x
> 

These errors are to be expected.  Here 'Basesalary' is a free-standing
function that has nothing whatsoever to do with the class you have.  

> basesalary = Basesalary() #Type Error: expected 1 argument, got 0

You declared the function to take an argument.  Since it is not a
class, there is no magic here with passing the new object as the first
argument.

> basesalary = Basesalary(self) #Name Error: there is no variable named self

Just as the error says, there is no variable 'self' here.  Self is
just the name commonly given to the first argument for functions
inside classes.

> basesalary = self.Basealary() #Name Error: there is no variable named self

Same here.  You haven't created a local variable named 'self'.

> basesalary = Position.Basesalary() #Name Error: there is no variable named
> 				   #Position

You haven't created a variable named 'Position' in the local
namespace.  I don't know exactly why this error, but I know that you
must have the 'Position' class defined somewhere else (not where you
executed this line of code).

> 
> So what I ended up doing was setting basesalary = self.Basesalary inside
> each function that needed it. That works but results in those functions
> being called many times, which has slowed my program down alot.
> 
> Am I doing this correctly? Is there a more efficient way. I don't want to
> call Basesalary() in the constructor, but I don't want to call it multiple
> times either.

Basesalary should be called in the init function.  This will init the
instance member to the correct value.  Then in each of the other
functions you have, use the instance member instead of recomputing the
value.

Are you familiar with OO design?  If not, let the list know and
someone (maybe me if I get to it first :-)) will explain it.

HTH,
-D