[Tutor] An OO question as relates to Python.

Magnus Lycka magnus@thinkware.se
Mon, 21 Oct 2002 10:25:19 +0200


At 16:50 2002-10-20 -0400, andy surany wrote:
>I understand the concept of classes (or think that I do....) and in fact,=
=20
>I've written a program in which I create a couple of classes - and=20
>"borrow" a couple from the work of others. So my question is really one of=
=20
>reference to a class - specifically in Python. In general, how do you=20
>maintain a reference to a class - which means, how do I really reference=20
>the functionality in a routine belonging to one class from another? I seem=
=20
>to be doing fine within a single class - but multiple classes are giving=20
>me problems.

I learnt a lot about OOP from Bertrand Meyer's Object
Oriented Software Construction. But it's really a brick...
Chapter 9 in the standard Python tutorial covers classes.

I think you should think more about objects and less
about classes. Typically, you only call classes when
you create objects, i.e. instances of the class. You
rarely make explicit calls to the functions (or rather,
methods) in a class. So it's the objects, or to be more
specific, the instances of the class you need references
to. The point with classes is that you collect code and
data on one bundle. This is the instance, often called
the object. The class is like a template for instances,
and you create instances by calling the class.

Just like you keep a reference to another type of
object, such as an integer or a list, you keep a
reference to an instance object with a variable.

This is no different in Python than in other languages.
I think the source of confusion are GUI programming
examples. In GUI's there are so many things happening
under the hood, and there are often implicit references
to objects which means that you can code in a style
which would otherwise mean that the objects disappeared
as soon as you had instanciated them. This makes these
GUI examples smaller and seemingly simpler, but since
more is done under the hood, it's bound to mislead the
OO novice.

Going back to python, you CAN call a class directly,
but typically you don't.

Maybe the following code might be of some help, where
instances of the SortedPersonList instanciate Person
objects, and place them in a list.

Perhaps this is all obvious to Andy, but a lot of people
are confused by OOP, so I think this might be useful.

---
class Person:
     def __init__(self, first, last):
         self.first =3D first
         self.last =3D last
     def whoami(self):
         return "My name is %s %s" % (self.first, self.last)
     def __cmp__(self, other):
         return cmp(self.last+self.first, other.last+other.first)

p =3D Person('Ron', 'Obvious')
p.whoami()
# Will print "My name is Ron Obvious"

class SortedPersonList:
     def __init__(self, listOfNames):
         self.persons =3D []
         for firstName, secondName in listOfNames:
             p =3D Person(firstName, secondName)
             self.persons.append(p)
         self.persons.sort()
     def printList(self):
         for p in self.persons:
             print p.whoami()

a =3D [('Andy', 'Surany'),
      ('Magnus', 'Lyck=E5'),
      ('Alex', 'Gillis'),
      ('Jay', 'Dorsey')]

recentTutorPosters =3D SortedPersonList(a)

recentTutorPosters.printList()
# Will print an alphabetical list with "My name is..." items.
---

Some comments:

The variable "self" which is used in places, corresponds to
the "this pointer" in for instance Java and C++. This is the
big difference between Python and the others. In Python, there
is no implicit this pointer. Explicit is better than implicit!

A method call such as "recentTutorPosters.printList()" can be
seen as a short form of: "SortedPersonList.printList(recentTutorPosters)".

Thus, the first parameter in any method in a class, should be an
instance object of the class in question. By convention this is
called "self".

The __init__ method is special. It is used to construct an
instance object. It has no return statement. "self" is always
returned. It's invoked automatiacally when you call the class.

E.g. p =3D Person('Ron', 'Obvious') could be seen as:

p =3D a new instance of the Person class
Person.__init__(p, 'Ron', 'Obvious')

Finally, the __cmp__ method is a special method. It's called
when you want to compare instances of a class. For instance,
if you write...

ron =3D Person('Ron', 'Obvious')
don =3D Person('Donald', 'Duck')
if ron < don:
     print "Ron's less than Don"

... the '<' operator will run:
Person.__cmp__(ron, don) and if __cmp__ returns a negative
number (meaning that ron was less than don) it will return
true. In the case above, __cmp__ is used when we sort the
list of Person instances.


--=20
Magnus Lyck=E5, Thinkware AB
=C4lvans v=E4g 99, SE-907 50 UME=C5
tel: 070-582 80 65, fax: 070-612 80 65
http://www.thinkware.se/  mailto:magnus@thinkware.se