Ok, now it’s time to draw breath a little and talk about something I mentioned a couple of tutorials ago – classes. We’ve used heaps of classes so far without noticing them. Classes are all round useful things, and there’s absolutely no avoiding classes if you do any but the most trivial of programs in Python. But that’s no problem because classes are really really neat and using them (generally) will improve your programming and your programs. Once you start using them you’ll wonder how you ever did anything without them.

This defines a class called allDads (the pass statement is necessary, because Python expects a class to have statements setting out the innards of the class. We have used pass as a sort of do nothing innard. We will do a more interesting example in a later tute). The class allDads is said to “inherit from” object (ie the thing named in the brackets). Which is to say, all the functions and data that object has, allDads has as well. As everything in Python is an object, so too allDads is also an object. However, allDads is just a definition, it is not an instance. We can make an “instance” of allDads as follows:

Nota bene: until you’re more familiar with classes, you should always define your class as inheriting from object. That is always put “(object)” after the name of the class.

At the moment we’ve made a pretty boring class and a pretty boring instance. The difference between classes and instances is that a class is a general description, while an instance is a particular. Thus “all dads” is a class (that is, the class of men who are parents), but “my dad” is a particular instance of that class.

When classes store data it is called an attribute. Attributes are referenced by joining the class name with the attribute name by a dot. Here’s an example:

>>> allDads.appearance = "Hairy"

Here “appearance” is the name of the attribute, right before we first try to assign a value to it Python creates it. It has been assigned the value “Hairy”. Let’s retrieve the value we’ve stored there:

>>> allDads.appearance
'Hairy'

What’s more, since myDad is an instance of allDads, it has inherited the attribute from the assignment to the class:

>>> myDad.appearance
'Hairy'

However, the class doesn’t inherit from the instances (which makes sense – just because my dad has certain attributes doesn’t mean all dads do):

Here we’ve made a second instance of allDads called thatSmellyKidsDad. thatSmellyKidsDadinherits the attributeappearance that the class has, but it doesn’t have the attribute we gave to the specific instancemyDad. The inheritance occurs at the time the instance is created. If you change the value of an instance later it doesn’t affect the attribute stored in any other instance, even if the attribute is inherited from the same classattribute.

Exercise 1: assign a different value to myDad.appearance and see if it changes thatSmellyKidsDad.appearance

Exercise 2: assign a different value to allDads.appearance and see if it changes myDad.appearance and thatSmellyKidsDad.appearance

Exercise 3: make some other attributes for myDad or thatSmellyKidsDad and assign values to them.

Hint:

Use this function to show all the attributes you’ve been adding:

def showAttributesOfInstance(c):
for i in dir(c):
if i[:2] != "__": # not a reserved attribute or function
if not callable(i): # not actually necessary as you can't define methods yet
print "%s:\t%s"%(i,c.__getattribute__(i))
>>> myDad.age = "28 and some months"
>>> showAttributesOfInstance(myDad)
age: 28 and some months
appearance: Hairy
description: My dad is, like, so the best dad in the world. What's more, he's particularly self effacing.

Extra Extra Bonus Points: understand how showAttributesOfInstance() uses introspection to do what it does.

Looking Forward

Just as you can store data in a class you can also store functions in a class. When data is stored in a class it’s called an attribute. When a function is stored in a class, it’s called a method. – But more on that later.