07 Object-oriented programming

This lesson is a little more advanced and covers object-oriented
programming in Python. It's not something you need for writing little
one-off scripts for yourself ... but knowing a little about Python
objects will help you if you try to read and understand open-source
Python programs, and it will also help you understand how to use
existing Python packages. It's especially common in GUI code -- no
matter what toolkit you use for the graphics, a GUI program will
usually have objects for windows, objects for dialogs, objects for
buttons, labels etc.

If you find today's lesson confusing, don't panic. If you haven't
done object-oriented programming, it takes a while to get the mindset.
As long as you know it exists and what words like "class" and "self"
mean, it's not so important to remember all the details.

===================== Objects ===========================

So what's an object, anyway?

An object is a data type that has some data of its own, and some
things it knows how to do with that data. It can be as simple as an
integer number, like 42, or as complicated as a browser window.

Suppose you have a list object, like mylist = [ 1, 2, 3 ]
It has its data -- all the objects in the list, and maybe some
additional information like how many items there are.

It also has some functions specific to the list. You could say
mylist.append(4), which would add a fourth list element at the
end. mylist.insert(4) also adds a fourth element, but adds it at the
beginning. mylist.remove(2) removes that element; mylist.reverse()
reverses the order of all the elements in the list.

All those functions -- append, insert, remove, reverse -- are called
"member functions" because they belong to -- are members of -- an object.

===================== Classes ===========================

An object is just one thing -- one variable containing one string,
one int, one Dictionary. (Of course, like a list or a dictionary, it
might contain more than one thing within itself, but you can still
think of the whole list as one thing.)

The word for a type of object, like string or list, is a class.

So if you say:

mylist = [ 1, 2, 3 ]

then mylist is a variable which is an object, and its class (type) is
a list.

If you're in the Python console and you ask what type mylist is:

>>> type(mylist)

it tells you it's a list. If it helps, you can think of "type" and
"class" as meaning the same thing.

=================== Defining a class ========================

You can define your own classes. Remember the flashcard exercise from
lesson 6? In that lesson, you had a dictionary of flashcards. But you
could also make a simple class called Flashcard:

class Flashcard :
def __init__(self, q, a) :
self.question = q
self.answer = a

def print_question(self) :
print self.question

Now you can create Flashcard objects:

card1 = Flashcard("What is a baby swan called?", "cygnet")
card2 = Flashcard("What is a group of larks called?", "exaltation")

You may be wondering about the capitalization. It's fairly common to
capitalize names of classes, but it's just a convention -- it's
not required.

======================== self ==============================

The big new thing you'll see with object-oriented code is this "self"
thing all over the place. Inside a class, "self" means the current
object. So when card1 is a Flashcard object, and its question is
"What is a baby swan called?", that's what self.question will be.

(If you've programmed in another object-oriented language, "self"
in Python is equivalent to "this" in most other languages. You could
even use "this" instead of "self", but don't: you'll confuse the heck
out of any other Python programmer who reads your code.)

You also have to add self as the first argument to just about any
class function. (There are a few exceptions, but that gets complicated
so let's not worry about that right now.)

You might wonder (especially if you've used other object-oriented
languages) why you have to keep typing these selfs everywhere.
Why doesn't Python just assume that if you say question, it means
self.question, and that class functions always know self means the
current object? If you wonder that, you're not alone. But that's the
way Python is, so just get used to seeing lots of "self." all over the
place in Python classes.

================== The init function ========================

It's not very useful to have a class if you can't create an object
of that class ... that's what the __init__ function is for.
(That's two underscores before init and two after it.)

def __init__(self, q, a) :

Use the __init__ function to set up any variables your class objects
must have. A Flashcard isn't useful if it doesn't have both a question
and an answer, so I made the init function take both q and a.

================== Other member functions ======================

The other member functions work the same way: they can refer to
self.question and self.answer. Inside class Flashcard, you could have:

line = "============================================="

def quiz_user(self) :
print self.line
self.print_question()
print self.line
ans = raw_input("? ")
if ans.strip().lower() == self.answer.strip().lower() :
print "Good job!"
return True

print "Sorry, the answer was:", self.answer
return False

Now there's a variable called line that's common to any object
of type Flashcard ... any Flashcard function, like quiz_user, can use
it by referencing self.line.

Now that we have the Flashcard object defined, writing a program
to quiz the user is easy:

cards = [
Flashcard("What is a baby swan called?", "cygnet"),
Flashcard("What is a group of larks called?", "exaltation"),
Flashcard("How many years does it take Neptune to orbit the sun?", "165"),
]

while True :
random.choice(cards).quiz_user()

========================= Homework =============================

1. Write a better loop for that flashcard program so that it exits
if the user types 'q', and prints out the number right or wrong.
Hint: you'll probably have to change quiz_user so it returns something
other than just True or False.

2. Write a Quiz class that creates flashcards and runs the loop to
quiz the user.

3. (optional) Rewrite your random sentence generation program from
lesson 5 so it's object oriented. Hint: you could make your list of
nouns, verbs etc. could be class variables, like "line" in my example
above.

4. (optional) Come up with a better homework assignment for object-
oriented programming in Python, then solve it. :-)