[Edu-sig] Introducing classes (from functions to methods)

Gregor Lingl glingl at aon.at
Tue Mar 7 00:46:59 CET 2006



Andre Roberge wrote:
> ... I thought of how I would go
> about to introduce classes, to users of rur-ple that have already
> written simple programs to make a robot (Reeborg) move in his world,
> both using the "function" notation and the OOP notation.
> 
...

Hi Andre and all of you,
may I give you a short sketch of my approach to this problem, just as a 
supplement to your approach. It mainly deals with the transition from 
writing functions to writing (classes and) methods and understanding the 
role of the self parameter:

You surely will not be surprised, that I do it with turtles. For your 
convenience with standard turtle.py  ;-)

Say, my students have written a short function

 >>> def polystep(length, angle):
	forward(length)
	left(angle)

to make the (anonymous) turtle (more exactly: Pen) draw spirals like

 >>> for l in range(4,80,4):
	polystep(l, 90)

Sometimes we say, we have taught the turtle a new word: polystep. So she 
now knows how to polystep.

Say, my students then have learned to use turtle objects:

 >>> joe=Pen()
 >>> ann=Pen()
 >>> ann.left(180)
 >>> for turtle in joe, ann:
	turtle.up()
	turtle.forward(100)
	turtle.down()

Wie now have two turtles at different positions on the screen. Now we 
want joe and ann to draw a spiral. We can do that this way:

 >>> for l in range(4,80,4):
	for turtle in joe, ann:
		turtle.forward(l)
		turtle.left(90)

We would appreciate it, if joe and ann both knew how to polystep:

 >>> for l in range(4,80,4):
	for turtle in joe, ann:
		turtle.polystep(l,90)

So - as a first step towards our goal - we want to modify polystep in 
order to pass a turtle object to it. This way it would know which turtle 
should perform the polystep:

 >>> def polystep(turtle, length, angle):
	turtle.forward(length)
	turtle.left(angle)

Now we can make our spirals like this:

 >>> for l in range(4,80,4):
	for turtle in joe, ann:
		polystep(turtle,l,90)

We would prefer the last line to be:
                 turtle.polystep(l,90)

i. e., that our turtles undertand how to polystep.

So we make a new class, (I omit some necessary explanations here
which you easily can fill in)

 >>> class MyPen(Pen):
	pass

which we can immediately investigate, e.g.:

 >>> joe = MyPen()
 >>> ann = MyPen()
 >>> joe.color("red")
 >>> joe.forward(50)
 >>> ann.left(90)
 >>> ann.forward(50)
 >>>

So we see, that MyPens (i.e. MyPen instances) know everything Pens know. 
MyPen is a subclass of Pen:

 >>> isinstance(joe, MyPen)
True
 >>> isinstance(joe,Pen)
True

Every MyPen is a Pen

Now we want MyPens to know more thatn Pens. So we have to teach them 
something new: we make polystep a method of MyPen. (The students know 
methods, e.g. forward as a method of Pen):

 >>> class MyPen(Pen):
	def polystep(turtle, length, angle):
		turtle.forward(length)
		turtle.left(angle)

We now can observe, that we have achieved, what we wanted:

 >>> joe = MyPen()
 >>> ann = MyPen()
 >>> ann.left(180)
 >>> for turtle in joe, ann:
	turtle.up()
	turtle.forward(100)
	turtle.down()

	
 >>> for l in range(4,80,4):
	for turtle in joe, ann:
		turtle.polystep(l,90)

works as desired.

We now have to explain, why there are only two arguments in the call of 
polystep. Lets try (arbitrary) three:

 >>> joe.polystep(1,2,3)
Traceback (most recent call last):
   File "<pyshell#49>", line 1, in ?
     joe.polystep(1,2,3)
TypeError: polystep() takes exactly 3 arguments (4 given)
 >>>

This shows, what the Pythoninterpreter thinks about this call. He counts 
joe as a fourth argument. So

 >>> joe.polystep(50, 90)
in fact has passed three arguments to the polystep method of MyPen, joe 
beeing passed to the first one, turtle. Really? Really! It does the same 
  as:
 >>> MyPen.polystep(joe, 50, 90)

That means, that the interpreter passes the turtle it*self* (for which 
the method is called) to the first parameter of the method. Taking into 
account, that one may chose variable names freely, but should chose them 
so, that the names appropriately describe the meaning, we replace the 
name turtle by the name self (and explain that that is a convention in 
Python):

 >>> class MyPen(Pen):
	def polystep(self, length, angle):
		self.forward(length)
		self.left(angle)

This last step changes nothing, except (hopefully) enhancing our 
understanding of the process of moving on from defining functions to 
defining methods, and especially of the role of self.

Regards,
Gregor




-- 
Gregor Lingl
Reisnerstrasse 3/19
A-1030 Wien

Telefon: +43 1 713 33 98
Mobil:   +43 664 140 35 27

Website: python4kids.net


More information about the Edu-sig mailing list