# [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)
>>>

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