Python:
Classes
What are classes?
Classes allow us to model
complicated, real-life
things in code
Until now, you've been using
simple data types
Numbers
Strings
To represent simple things
Numbers
length = 3
price = 5.99
count = 0
length = 3
price = 5.99
count = 0
Strings
name = "George"
poem = "Roses are Red\nViolets are Blue"
option = "n"
name = "George"
poem = "Roses are Red\nViolets are Blue"
option = "n"
Booleans
discount = True
show_help = False
discount = True
show_help = False
But what if you need to
represent something
more complicated
than a number?
(c)Tomo.Yun (www.yunphoto.net/en/)
Meet Spencer
(He's your goldfish)
We're going to put
Spencer into a program
Let's make a virtual
aquarium for him
But how can you represent
a Goldfish in Python?
First, think about fish
Not a specific fish,
but the
idea
of fish
Not a specific fish,
but the idea of fish
but the idea of fish
What makes a fish a fish
rather than, say, a lobster?
We define these fish-y
characteristics as a "class"
Fish have scales
Breathe in water
Swim
Now think about Spencer
Spencer is a specific fish
He is your fish,
swimming in your fishbowl
We call Spencer an
"instance" of a fish
There are other instances
of fish (for example, your
sister's goldfish)
But they're all Fish
class = the idea of a fish
instances = the actual fish
Let's Code
(follow along!)
Define a basic Fish class
class Fish:
pass
class Fish:
pass
capital "F", please
pass = "do nothing" (for now)
Make a fish
>> Fish()
<... Fish instance at ...>
>> Fish()
<... Fish instance at ...>
Make another
>> Fish()
<... Fish instance at ...>
>> Fish()
<... Fish instance at ...>
These are different fish!
>> a = Fish()
>> b = Fish()
>> a == b
False
>> a = Fish()
>> b = Fish()
>> a == b
False
Our Fish class isn't very fish-y
Let's add some fishy-ness
class Fish:
breathes_in_water = True
skin = "scales"
class Fish:
breathes_in_water = True
skin = "scales"
These variables exist on fish we create
>> myfish = Fish()
>> myfish.skin
"scales"
>> if myfish.breathes_in_water:
... print "Glug glug!"
Glug glug!
>> myfish = Fish()
>> myfish.skin
"scales"
>> if myfish.breathes_in_water:
... print "Glug glug!"
Glug glug!
You can also add functions
(a.k.a methods)
class Fish:
def move(self, speed):
print "swimming %s!" % speed
class Fish:
def move(self, speed):
print "swimming %s!" % speed
>> myfish = Fish()
>> myfish.move("fast")
swimming fast!
>> myfish = Fish()
>> myfish.move("fast")
swimming fast!
This gives your fish behavior
Wait a minute!
(You might say)
.move() requires 2 parameters,
and you only passed 1!
...
def move(self, speed):
...
myfish.move("fast")
...
def move(self, speed):
...
myfish.move("fast")
Python automatically puts
"myfish" into the "self" variable
class Fish:
def move(self, speed):
print self.name + " is moving " + speed + "!"
>> myfish = Fish()
>> myfish.name = "Spencer"
>> myfish.move("fast")
Spencer is moving fast!
class Fish:
def move(self, speed):
print self.name + " is moving " + speed + "!"
>> myfish = Fish()
>> myfish.name = "Spencer"
>> myfish.move("fast")
Spencer is moving fast!
To customize your fish,
you can put any variables
on the instance
>> myfish = Fish()
>> myfish.name = "Spencer"
>> myfish.color = "Gold"
>> myotherfish = Fish()
>> myotherfish.name = "Susan"
>> myotherfish.color = "Blue"
>> myfish = Fish()
>> myfish.name = "Spencer"
>> myfish.color = "Gold"
>> myotherfish = Fish()
>> myotherfish.name = "Susan"
>> myotherfish.color = "Blue"
But that takes too much typing
(There's a shortcut)
Introducing __init__
__init__ is called whenever you
create a fish instance
class Fish:
def __init__(self):
print "Fish init!"
>> myfish = Fish()
Fish init!
>> Fish()
Fish init!
class Fish:
def __init__(self):
print "Fish init!"
>> myfish = Fish()
Fish init!
>> Fish()
Fish init!
(the double underscores means it is "special")
Any parameters you pass into Fish()
will be passed to __init__()
class Fish:
def __init__(self, fish_name):
self.name = fish_name
>> myfish = Fish("Spencer")
>> myfish.name
"Spencer"
class Fish:
def __init__(self, fish_name):
self.name = fish_name
>> myfish = Fish("Spencer")
>> myfish.name
"Spencer"
(See if you can add "color" to the init also)
Let's review a full Fish class
class Fish:
breathes_in_water = True
skin = "scales"
def __init__(self, fish_name, fish_color):
self.name = fish_name
self.color = fish_color
def move(self, speed):
print self.name + " is moving " + speed + "!"
>> spencer = Fish("Spencer", "Gold")
>> print spencer.move("slowly")
Spencer is moving slowly!
class Fish:
breathes_in_water = True
skin = "scales"
def __init__(self, fish_name, fish_color):
self.name = fish_name
self.color = fish_color
def move(self, speed):
print self.name + " is moving " + speed + "!"
>> spencer = Fish("Spencer", "Gold")
>> print spencer.move("slowly")
Spencer is moving slowly!
Now the fun starts
If we're building an aquarium
we're going to need more than
one kind of fish
One way you might think
is to store the species on Fish
class Fish:
def __init__(self, species):
self.species = species
spencer = Fish("Goldfish")
susan = Fish("Flounder")
class Fish:
def __init__(self, species):
self.species = species
spencer = Fish("Goldfish")
susan = Fish("Flounder")
But that is just a string.
What if behavior is different?
Okay, then let's create a
different class for Flounder
class Goldfish:
breathes_in_water = True
skin = "scales"
def move(self, speed):
print "Swimming upright %s!" % speed
class Flounder:
breathes_in_water = True
skin = "scales"
def move(self, speed):
print "Swimming sideways %s!" % speed
class Goldfish:
breathes_in_water = True
skin = "scales"
def move(self, speed):
print "Swimming upright %s!" % speed
class Flounder:
breathes_in_water = True
skin = "scales"
def move(self, speed):
print "Swimming sideways %s!" % speed
That seems tedious
Plus, there's so much duplicated code!
What if they could share
the things that they
have in common?
Introducing parent classes
class Fish:
skin = "scales"
class Goldfish(Fish): # <- Fish specified as parent
def move(self, speed):
print "Moving %s" % speed
>> spencer = Goldfish()
>> spencer.skin # <- So it has "skin" from Fish
"scales"
class Fish:
skin = "scales"
class Goldfish(Fish): # <- Fish specified as parent
def move(self, speed):
print "Moving %s" % speed
>> spencer = Goldfish()
>> spencer.skin # <- So it has "skin" from Fish
"scales"
Classes will "inherit" all of
their parent's behavior
and properties
Child classes can also
override parent's behavior
class Fish:
color = "Blue" # Default fish color is Blue
skin = "scales"
class Flounder(Fish):
pass # Inherits color = "Blue" from parent
class Goldfish(Fish):
color = "Gold" # Override color for Goldfish
>> susan = Flounder()
>> susan.color
"Blue"
>> spencer = Goldfish()
>> spencer.color
"Gold"
class Fish:
color = "Blue" # Default fish color is Blue
skin = "scales"
class Flounder(Fish):
pass # Inherits color = "Blue" from parent
class Goldfish(Fish):
color = "Gold" # Override color for Goldfish
>> susan = Flounder()
>> susan.color
"Blue"
>> spencer = Goldfish()
>> spencer.color
"Gold"
We can test if a fish is
a certain type
class Fish:
pass
class Goldfish(Fish):
pass
class Flounder(Fish):
pass
>> spencer = Goldfish()
>> isinstance(spencer, Fish)
True
>> isinstance(spencer, Goldfish)
True
>> isinstance(spencer, Flounder)
False
class Fish:
pass
class Goldfish(Fish):
pass
class Flounder(Fish):
pass
>> spencer = Goldfish()
>> isinstance(spencer, Fish)
True
>> isinstance(spencer, Goldfish)
True
>> isinstance(spencer, Flounder)
False
Now that you know about
parent classes, always give
your top class a parent of
"object" (2.7 only)
class Fish(object):
pass
class Goldfish(Fish):
pass
class Fish(object):
pass
class Goldfish(Fish):
pass
object is the mother of all parent classes
Read this like
Goldfish is a more specific
Fish, which is a more specific
Object
(Object being the most general thing we can arrive at)
Let's put some fish into
an aquarium
Try this by yourself before
continuing
Hint:
Make another class called Aquarium that holds
instances of fish, and assign some fish instances to it
instances of fish, and assign some fish instances to it
Aquarium class
class Aquarium(object):
fish = []
def __init__(self, fish):
self.fish = fish
class Fish(object):
color = "Blue"
def __init__(self, name):
self.name = name
class Goldfish(Fish):
color = "Gold"
class Flounder(Fish):
pass
>> my_fish = [Goldfish("Spencer"), Goldfish("Vladimir"), Flounder("Susan")]
>> my_aquarium = Aquarium(my_fish)
>> for fish in my_aquarium.fish:
... print fish.name
Extra credit: Feeding your fish
Implement a .feed() method
on both your aquarium class
and your fish class
Feeding your aquarium then
in turn feeds each of the fish
in it
Feeding your fish
class Aquarium(object):
...
def feed(self, food):
for fish in self.fish:
fish.eat(food)
class Fish(object):
...
def eat(self, food):
print self.name + " is eating " + food + "!"
class Goldfish(Fish):
pass
>> my_aquarium = Aquarium([Goldfish("Spencer"), Goldfish("Susan")])
>> my_aquarium.feed("flakes")
Spencer is eating flakes!
Susan is eating flakes!
That's all folks!
Questions?
Stop by http://reddit.com/r/learnpython
Classes in Python
By Jason Myers
Classes in Python
A brief tutorial on Python classes, initially used as a supplement for http://learnpythonthehardway.com/book
- 12,715