Classes and Objects

Example: Student Class

What is a class? No, not CS1. In Python, class is a reserved word.

A class is a collection of methods. That’s it! Let’s give an example.

class Student:

    def __init__(self, name, id):
        self.name = name
        self.id = id

Here is a sample class. The only method that is defined is __init__. This method is special because it defines how to create objects!

What’s an object? An object is any data belonging to a class. Everything in Python is an object. All data belongs to some class. The class Student can create Student objects, and every Student object has two attributes: a name and an id.

How do I know that? I look at the __init__ method which defines how to create objects. (Note that not every class has an __init__ method. If it does not, you cannot create objects from that class.)

Every instance of the class Student (another word for objects) has those two attributes, per the __init__ method. Pretty handy.

Let’s create a student object and fill it with attributes.

chander = Student('Chander', '..Nice try. #topSecret')

That’s it! Notice to create a new object we used the class name, and not the __init__ method; using the class name automatically calls the __init__ method, and this way is preferred because Python does some other operations behind the scenes that we won’t discuss here.

How do I access the properties of chander?

print chander.name
print chander.id

Cool! It prints out the values we gave it. The . operator is used to do this. But what happens when we do an attribute we never gave?

print chander.height

Python spits out the following error:

AttributeError: Student instance has no attribute 'height'

An AttributeError! In this class we will refer to these as instance variables. They are the variables defined by the __init__ method – the variables that every object of the Student class is guaranteed to have. They are also called attributes. Here, Python is saying that this particular Student object has no such attribute called “height”, and of course it is correct.

But how is a class a collection of methods then? Well, let’s add some more methods and find out. Wouldn’t it be nice to know what their major is? No. No one cares. Let’s find out their most embarassing secret instead.

def get_secret(self):
    return self.secret

Uh oh. But aren’t we going to run into the same AttributeError as before? Yes. So I guess we’ll have to change our __init__ method accordingly. Here it is.

def __init__(self, name, id, secret=None):
    if secret is None:
        self.secret = "Nunya. Nunya beezwax."
    else:
        self.secret = None
    self.name = name
    self.id = id

Okay. What else? How about their hobbies.

def get_hobby(self):
    if self.hobby == []:
        return "I am a CS major. I have no hobbies."
    return self.hobby

Darn. That __init__ method again. Let’s make the changes.

def __init__(self, name, id, secret=None, hobby=None):
    self.secret = "Nunya. Nunya beezwax" if secret is None else secret
    self.name = name
    self.id = id
    self.hobby = [] if hobby is None else hobby

That last statement is Python’s version of the ternary operator. It’s a neat little trick that makes the two-line if-statement we did for self.secret into a nice little one-liner. For brevity, I changed the way we did secret, too.

What we mean by “a class is a collection of methods” is that every object of the Student class has access to every method defined within that class. For example, every new Student object we create can already implement the get_hobby and get_secret methods.

chander = Student("chander", 1, "I made a twelve year-old cry in Call of Duty.")
grumpyCat = Student("grumpyCat", 2, "No.", "No.")
doug = Student("Doug", 3, "I have just met you, and I LOVE you!", "SQUIRREL!")
snipe = Student("Snipe", 4, None, "Chocolate.")

print snipe.get_secret()

Sweet. Very convenient.

Self Parameter

Surely you’ve noticed by now that every class method has self as the first parameter, but when you call the method, you don’t need to put in self.

This self refers to the object that is calling the method. In otherwords, when you do

chander.get_hobby()

self is then substituted with chander when that method is called. In the method headers, self is just a placeholder. It’s a promise to Python saying “I know this is a method, and it can’t be called by itself, but I promise that some object will be calling this. For now let’s just agree to call that object self.”

Every method that is called via an object must have a self parameter. Later on, we’ll look at things called class methods which aren’t called via objects. Those don’t need self.

Functions vs Methods

The difference between functions and methods is often subtle but extremely important.

A function is independent of any class or object. You call a function like this

function_name_example(example, parameters, go, here)

A method is always associated with some class. You call a method like this

object_of_class.method_name(parameters, go, here)

What’s the minimum number of parameters for a function? Zero. A function doesn’t have to have any parameters.

What about for a method? One. Remember, self is always necessary for the methods we’ll be dealing with. Without a class you cannot have methods. Period. No exceptions.