Software Carpentry logo

Python Basic Object-Oriented Programming

April 24, 2010: We are pleased to announce that Version 4 of this course is now under development. For updates and an early peek at the content, please check out the Software Carpentry blog at http://www.software-carpentry.org/blog/.

1) Introduction

for time in simulation_period:
    for thing in world:
        if type(thing) is plant:
            update_plant(thing, time)
        elif type(thing) is fish:
            update_fish(thing, time)
        elif type(thing) is creepy_crawly:
            update_creepy_crawly(thing, time)

2) Objects to the Rescue

for time in simulation_period:
    for thing in world:
        thing.update(time)

3) You Can Skip This Lecture If...

4) Abstract Data Types

5) Classes and Instances

6) Defining a Class

class Empty(object):
    pass

7) Creating an Instance

if __name__ == '__main__':
    first = Empty()
    second = Empty()
    print 'first has id', id(first)
    print 'second has id', id(second)
first has id 5086860
second has id 5086892

8) Methods

class Greeting(object):
    def say(self, name):
        print 'Hello, %s!' % name

if __name__ == '__main__':
    greet = Greeting()
    greet.say('object')
Hello, object!

9) Creating Members

class Point(object):

    def set_values(self, x, y):
        self.x = x
        self.y = y

    def get_values(self):
        return (self.x, self.y)

    def norm(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

if __name__ == '__main__':
    p = Point()
    p.set_values(1.2, 3.5)
    print 'p is', p.get_values()
    print 'norm is', p.norm()
p is (1.2, 3.5)
norm is 3.7
Creating a Simple Point

Figure 13.2: Creating a Simple Point

10) Encapsulation

p = Point()
p.x = 3.5
p.y = 4.25
print 'point is', p.get_values()
point is (3.5, 4.25)

11) Constructors

class Point(object):

    def __init__(self, x=0, y=0):
        self.reset(x, y)

    def reset(self, x, y):
        assert (type(x) is int) and (x >= 0), 'x is not non-negative integer'
        assert (type(y) is int) and (y >= 0), 'y is not non-negative integer'
        self.x = x
        self.y = y

    def get(self):
        return (self.x, self.y)

    def norm(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

if __name__ == '__main__':
    p = Point(1, 1)
    print 'point is initially', p.get()
    p.reset(1, 1)
    print 'p moved to', p.get()
point is initially (1, 1)
p moved to (1, 1)

12) Constructor Style

13) Special Methods

class Point(object):

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return '(%4.2f, %4.2f)' % (self.x, self.y)

if __name__ == '__main__':
    p = Point(3, 4)
    print 'point is', p
point is (3, 4)

14) New Classes from Old

15) Inheritance Example

class Organism(object):

    def __init__(self, common_name, sci_name):
        self.common_name = common_name
        self.sci_name = sci_name

    def get_common_name(self):
        return self.common_name

    def get_sci_name(self):
        return self.sci_name

    def __str__(self):
        return '%s (%s)' % (self.common_name, self.sci_name)

class Mammal(Organism):

    def __init__(self, common_name, sci_name, body_temp, gest_period):
        Organism.__init__(self, common_name, sci_name)
        self.body_temp = body_temp
        self.gest_period = gest_period

    def get_body_temp(self):
        return self.body_temp

    def get_gest_period(self):
        return self.gest_period

    def __str__(self):
        extra = ' %4.2f degrees / %d days' % (self.body_temp, self.gest_period)
        return Organism.__str__(self) + extra

if __name__ == '__main__':
    creature = Mammal('wolf', 'canis lupus', 38.7, 63)
    print creature
wolf (canis lupus) 38.70 degrees / 63 days
Memory Model for Inheritance

Figure 13.3: Memory Model for Inheritance

16) Overriding Methods

17) Polymorphism

class Bird(Organism):

    def __init__(self, common_name, sci_name, incubate_period):
        Organism.__init__(self, common_name, sci_name)
        self.incubate_period = incubate_period

    def get_incubate_period(self):
        return self.incubate_period

    def __str__(self):
        extra = ' %d days' % self.incubate_period
        return Organism.__str__(self) + extra

if __name__ == '__main__':
    creatures = [
        Bird('loon', 'gavia immer', 27),
        Mammal('grizzly bear', 'ursus arctos horribilis', 38.0, 210)
    ]
    for c in creatures:
        print c
loon (gavia immer) 27 days
grizzly bear (ursus arctos horribilis) 38.00 degrees / 210 days

18) Duck Typing

class Mineral(object):

    def __init__(self, common_name, sci_name, formula):
        self.common_name = common_name
        self.sci_name = sci_name
        self.formula = formula

    def get_common_name(self):
        return self.common_name

    def get_sci_name(self):
        return self.sci_name

    def __str__(self):
        return '%s/%s: %s' % (self.common_name, self.sci_name, self.formula)

if __name__ == '__main__':
    things = [
        Mammal('arctic hare', 'Lepus arcticus', 40.1, 50),
        Mineral("fool's gold", 'iron pyrite', 'FeS2')
    ]
    for t in things:
        print t.get_common_name(), 'is', t.get_sci_name()
arctic hare is Lepus arcticus
fool's gold is iron pyrite

19) The Liskov Substitution Principle

20) Tidal Pools Revisited

21) Class, Responsibility, Collaborator

22) Summary