Spring Semester 2007


Lecture Seven: Classes and objects.
We spoke about methods last week. Very important topic.

The Tic-Tac-Toe program is an example of a fairly large program. In terms of projects' size it's effectively a lower bound.

Good to know. We need to review the Tic-Tac-Toe in class once.

Once we do that we start pressing further. What do we cover next?

Objects. Classes and objects. Object-Oriented Programming.

Precisely. Well, let's get started.

Here's how we define a simple object: How do you use this code?
class critter(object):
    def talk(self):
        print "Hi, I am a critter."

Create critters like this:
>>> a = critter()
>>> a
<__main__.critter object at 0x00D55070>
>>> a.talk()
Hi, I am a critter.
>>> 
Ah, I see: you can run them too.

Can you create a list of critters? Sure, here's how it's done:
>>> critters = []
>>> for i in range(6):
	critters.append(critter())

>>> critters
[<__main__.critter object at 0x00D55210>, 
 <__main__.critter object at 0x00D55270>, 
 <__main__.critter object at 0x00D552D0>, 
 <__main__.critter object at 0x00D552F0>, 
 <__main__.critter object at 0x00D55310>, 
 <__main__.critter object at 0x00D55330>]

>>> for i in range(len(critters)):
	critters[i].talk()

Hi, I am a critter.
Hi, I am a critter.
Hi, I am a critter.
Hi, I am a critter.
Hi, I am a critter.
Hi, I am a critter.
>>> 

What's the purpose of all this? So far we're just exploring, learning to create objects.

What's the contents of these objects? So far, each one of them has a method inside.

Here's a picture of Little Critter. Little Critter by Mercer Meyer, indeed.

Let's make the critters different. Here's a modified example:
class critter(object):
    def __init__(self, name):
        self.name = name
        print "Critter", name, "created."
    def talk(self):
        print "Hi, I am a critter ", self.name

import random

def test():
    names = ["Granger", "Dunleavy", "Tinsley", "Diogu", "Foster"]
    pacers = []
    for i in range(len(names)):
        pacers.append(critter(names[i]))
    while pacers:
        i = random.randrange(len(pacers))
        pacers[i].talk()
        pacers = pacers[0:i] + pacers[i+1:]

So what do you get when you run this? Five starters (let's say) entering the fieldhouse.
>>> test()
Critter Granger created.
Critter Dunleavy created.
Critter Tinsley created.
Critter Diogu created.
Critter Foster created.
Hi, I am a critter  Tinsley
Hi, I am a critter  Diogu
Hi, I am a critter  Foster
Hi, I am a critter  Dunleavy
Hi, I am a critter  Granger
>>> 

Every time in a different formation. If you were to run it again and again, yes.

Let's design a type of fraction objects. Every fraction is a pair of integers.

So we start like this: What is the purpose of the second method?
class fraction(object):
    def __init__(self, num, den):
        self.num = num
        self.den = den
    def __str__(self):
        return str(self.num) + "/" + str(self.den)

__init__ is the constructor. What's the other one for?

__str__ is a standard name for what we want to see if the object is ever invoked in a string context. That's just like Java's .toString method.
>>> f = fraction(2, 4)
>>> print f
2/4
>>> 

What about the fraction's lowest term representation? We need a procedure to calculate the greatest common divisor.

If we had it, would we store it at the object level? Perhaps not. Below we make it static (class method).
class fraction(object):

    def gcd(a, b):
        m = max(abs(a), abs(b))
        n = min(abs(a), abs(b))
        if n == 0:
            return 0
        else:
            d = n
            while not (m % d == 0 and n % d == 0):
                d -= 1
            return d

    gcd = staticmethod(gcd)

    def __init__(self, num, den):
        self.num = num / fraction.gcd(num, den)
        self.den = den / fraction.gcd(num, den)

    def __str__(self):
        return str(self.num) + "/" + str(self.den)

Next we need to teach fractions to add and multiply themselves. There are two ways to do it and we will discuss them both.

Great. Show me 2-3 more examples with what we have so far. Sure enough. Here you go:
>>> f = fraction(2, 4)
>>> print f
1/2
>>> f = fraction(-9, 3)
>>> print f
-3/1
>>> f = fraction(12, 18)
>>> print f
2/3
>>> 

So what do we do next time? Private instance members, accessors and mutators.

In terms of programs? We'll finish fractions and we start a largish case-study.

What case-study? We'll implement the game of Blackjack (in lab).

Interesting... Homework Three will be posted this week.

Deadlines are still as flexible as you need them. And next week we will discuss File I/O.

Sounds interesting. I bet.

Updated by Adrian German for A202/A598