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




Booleans







To represent simple things

Numbers

length = 3price = 5.99count = 0

Strings

name = "George"poem = "Roses are Red\nViolets are Blue"option = "n"

Booleans
discount = Trueshow_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




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


     capital "F", please

     pass = "do nothing" (for now)

Make a fish

>> Fish()
<... Fish instance at ...> 


Make another

>> Fish()
<... Fish instance at ...> 


These are different fish!

>> 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" 


These variables exist on fish we create

>> 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


>> 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")

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!

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"


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!

(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"


(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!





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")


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



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"


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"

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

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


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

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?


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

  • 2,011