[Tutor] Help with understanding classes
Steven D'Aprano
steve at pearwood.info
Sat May 21 13:49:27 CEST 2011
On Sat, 21 May 2011 08:24:34 pm Robert Sjöblom wrote:
> I'm trying to wrap my head around classes and their attributes, but
> am having a hard time doing so. The websites and books that I have
> consulted haven't been much help; most of them assume prior
> programming/oop experience, something I lack.
Let's start with a simple question -- what is an object? In programming,
an object is a thing that combines data and behaviour together in one
handy package. Back in the Dark Ages *wink*, code and behaviour were
always separate, so you would have to design a data structure in one
place of your program, then write functions to manipulate it somewhere
else. If you had two different data structures which needed similar
actions, you had to jump through hoops to keep the functions for one
separate from the functions of the other.
But objects let you keep related pieces of code together, so they don't
get in the way of unrelated code with the same name:
class Artist:
def draw(self):
print("I splashed paint on the canvas until it looked like"
" my mother on a rocking horse.")
class GunSlinger:
def draw(self):
print("The stranger reached for his gun, but I was too"
" quick for him and plugged him full of lead.")
The function (actually "method") called draw for Artists doesn't get
over-ridden by the method with the same name for GunSlingers:
>>> whistler = Artist()
>>> wyatt_earp = GunSlinger()
>>> whistler.draw()
I splashed paint on the canvas until it looked like my mother on a
rocking horse.
>>> wyatt_earp.draw()
The stranger reached for his gun, but I was too quick for him and
plugged him full of lead.
Here you see object code in action. You start with a class, which is
something vaguely like a template. (It's actually nothing like a
template, but that will do for now.) Before you can use the class, you
normally have to instantiate it.
Think of it like this: in the real world, "car" is a kind of machine, or
if you prefer, a *class* of machine. But you can't just get into the
abstract class of "car" and drive to the shops, you need an actual,
concrete, physical car: an *instance* of the class. In object oriented
programming ("OOP"), this is normally the same: you create an instance
of the class, and then work with that. The instance gets its behaviour
(and sometimes its data) from the class.
The examples above are classes with behaviour only, no data or state.
They never change. That's not very useful. Normally you want to store
data in the class instance, sometimes in the class itself. Here's an
example:
class Paper:
colour = "white"
size = "A4"
This defines a class with no behaviour, only state. In this case, it has
two attributes, colour and size. The values stored in the class are
global defaults: all Paper instances share the same value. But you can
give individual instances their own independent value by assignment:
>>> sheet = Paper()
>>> sheet.colour
'white'
>>>
>>> another_sheet = Paper()
>>> another_sheet.size = "A5" # cut the paper in half
>>> another_sheet.colour = "green" # and paint it
>>> another_sheet.colour # check that the change is stored
'green'
>>>
>>> sheet.colour # and check that the other sheet is unchanged
'white'
Normally though, you don't need or want to set default state that
applies to all instances. In the above Paper example, it is harmless,
but sometimes it can lead to bugs, so be careful with class attributes.
So although attributes common to all instances of a class can sometimes
be useful, generally people try to avoid them, and it is more common to
put off defining the instance's attributes until the instance is
created. For that, Python has a special method called "__init__"
(that's two underscores at the front and back). When you create an
instance by calling Paper(), the __init__ method (if any) is
automatically called by Python.
class Paper:
def __init__(self, colour="white", size="A4"):
self.colour = colour
self.size = size
Now the attributes no longer live inside the class, but inside the
instance. Paper instances no longer share global state. Each instance
gets its own independent attribute for colour and size, which you can
specify when you create it:
>>> sheet = Paper("blue", "Foolscap")
>>> sheet.colour
'blue'
Now, I've skimmed over a couple of important things here. Firstly,
syntax: in Python, the syntax for attribute access is with a dot:
paper.size
lets you retrieve the attribute. To set the attribute, you simply assign
to it:
paper.size = "A3"
Notice that dot is the same syntax used for accessing methods:
whistler.draw()
That's because in Python, methods are just another attribute, only you
can call them with () syntax. This lets you do all sorts of cool and
advanced things, like store a method somewhere to use it later:
import random
if random.random() < 0.5:
method = wyatt_earp.draw # no parentheses!
else:
method = whistler.draw
# later...
method() # call the method
but I digress.
The other thing I glossed over was the mysterious "self" parameter in
the method definitions. Remember, methods are defined inside the class,
not inside the instance. When you call a method, how does the class
know which instance it should look at? The answer is, Python does some
sleight of hand in the background, changing what you write:
whistler.draw()
into what actually gets executed:
Artist.draw(whistler)
That's moderately advanced though, you don't need to care about it,
*except* that you have to remember to declare a parameter in all your
methods to hold that auto-magic instance argument. Conventionally, we
call it "self", but you can call it anything you like. (You can, but
you shouldn't.) Forgetting to declare "self" in your methods is one of
the more common source of bugs.
That's pretty much all you need to know to start using objects. There's
a lot more though: inheritance, class methods and static methods (as
opposed to ordinary methods), properties, descriptors (advanced!),
slots, and more. But one step at a time.
Any questions, don't hesitate to ask!
--
Steven D'Aprano
More information about the Tutor
mailing list