Classes and Object-Oriented Programming in Python

What is object-oriented programming?

A set of general programming techniques driven by data interaction such that

Data is organized into human-recognizable classes and

Objects of these classes contain methods that act upon their data

How is that different from other kinds of programming?

In solely procedural programming languages like FORTRAN, BASIC, or C, flow of control is external to the data

Loops act on data�data cannot act on �itself�

So far, our Python programming has been mostly procedural:

>>> length = len('fred')

>>> print length

4

But we have also used some object-oriented approaches:

>>> 'fred'.upper()

'FRED'

In the first example, we applied a global function len() to find the length of the string 'fred'

But in the second example, the literal string 'fred' applies the string-specific method upper() to itself

We will explore how to make classes and objects of classes that behave in this way

What is a class?

A class is a template for a data structure and a collection of methods that operate upon the data

The person who designs a class is usually interested in modeling high-level human thinking about the data

Consider data about lakes�they have

A name

Maximum depth

Surface area

Volume

A host of measurements on biological, environmental, and physical characteristics

Classes typically specify methods that act on an individual object�s data

The Lake class might have complex methods that could determine

How a storm event might raise the surface level

How a point-source pollution event might disperse throughout the body of the lake

And so on�

A Lake class would allow us to make an object for every lake we want to represent

Each object�s data is generally independent of every other object

What is an object?

An object is an instance of a class

An object has data associated with itself representing a specific example of the class

For example, we could create a Lake object for each one of the NY State Finger Lakes

Each object would share the same descriptive structure but its observations would be different from other objects in the same class

seneca and cayugaboth have name and maximum depth fields, but their values are different

When an object calls a method on itself, the method works on its own data

In this example, name1 and name2 are both objects of the string class

However, the objects represent different data

When name1 and name2 call the upper() method, they do so on their own data:

>>> name1 = 'fred'

>>> name2 = 'mary'

>>> name1.upper()

'FRED'

>>> name2.upper()

'MARY'

Some ways to think about classes and objects

A class is like an empty template or form; an object is like a completed form

A class is like a cookie cutter; an object is the cookie

In either case, an object holds data specific to a particular instance of a class

The class itself is a data type, like an integer or a string

Creating a simple geometric class

Let�s create a UTM_Coord class that represents a point in UTM coordinates

Such a point has some common properties (not using Military Grid IDs here):

Zone number (integer),

Zone hemisphere identifier (character)

Easting (floating point)

Northing (floating point)

By creating a UTM_Coord class, we can create objects that refer to individual locations (all with UTM coordinate values)

To keep things simple, these examples will be created and run in an IDE like Sublime

Although classes of these types likely exist in Python graphics libraries, we will create them here to tryout some techniques

The code for the UTM_Coord class is here (save to a text file called UTM_Coord.py)

class UTM_Coord:

def __init__( self, e, n, z, h):

���� self.easting = e

���� self.northing = n

���� self.zone = z

���� self.hemisphere = h

Looking at each line of code,

class UTM_Coord:

class is a Python keyword; UTM_Coord is the class name

def __init__( self, e, n, z, h):

This is the first line of the class constructor definition

A class constructor initializes an object when it�s created

This constructor takes 5 arguments:

self (identifies this particular object)

easting, northing (the 2D floating point coordinates)

zone, hemisphere (the integer and character identifying the zone (1-60) and hemisphere(N/S))

A constructor in any class will always be called __init__()

2 underscore characters precede and follow the word init

���� self.easting = e

���� self.northing = n

���� self.zone = z

���� self.hemisphere = h

To create a class member variable, you just have to introduce a new name like this:

self.newName

where newName is your chosen variable name

So, each of these lines creates a class member variable (e.g. self.easting) and assigns one of the constructor arguments to it

You can find the code for the following section here (save it as Using_UTM_Coord.py in the same folder as UTM_Coord.py)

Now we can create an object of the UTM_Coord class like this:

import UTM_Coord as uc

myFavoriteSpot = uc.UTM_Coord(580000, 4720000, 18, 'N')

And query its properties like this (no indent):

print 'My favorite place is at UTM coordinates ' + \

str(myFavoriteSpot.easting) + 'mE, ' + \

str(myFavoriteSpot.northing) + 'mN, zone ' + \

str(myFavoriteSpot.zone) + myFavoriteSpot.hemisphere

Note: the \ character allows you to continue a statement on the next line

Great! Except that it�s a pain to always have to write a print statement like this

Let�s create a class method, coordinates_to_string(), that will allow us to convert each point�s coordinate data to a string

Start this method definition after the last line of the constructor at the same indent level as the first line of the constructor

def coordinates_to_string(self):

���� return str(self.easting) + 'mE, ' + \

���� str(self.northing) + 'mN, zone ' + \

���� str(self.zone) + self.hemisphere

Methods defined within a class will have at least one parameter, self, that refers to the particular object

In this case, we just return a string very similar to the one we created for the print statement we created before

But now, we don�t have to customize it for every point�it will be done automatically

Add this line of code (with no indent) at the end of your file:

print 'My favorite place is at UTM coordinates ' + \

myFavoriteSpot.coordinates_to_string()

Try out the UTM_Coord on another point:

copacabana = UTM_Coord(686336.05, 7458567.56, 23, 'S')

print 'My favorite place in S America is ' + \

copacabana.coordinates_to_string()

A few words about __main__

Where exactly does a Python program start?

We have created Python modules that start with �the first line of code at the top of the file�

This is actually the scope of the __main__ function which is created anonymously for you

You can use this to your advantage if you want to test features in a single module

Suppose you wanted to create a class in an individual module (like UTM_Coord) but also wanted to test the method to see if it works

You could just put code after the class that would test it

But this code would run in every module that imported UTM_Coord.py

Instead, test the code inside this if statement:

if __name__ == '__main__':

myPlace = UTM_Coord(580101, 4720202, 18, 'N')

print "myPlace: " + myPlace.coordinates_to_string()

Now this test will only run if UTM_Coord.py is run directly, but not if it is imported from another module (like UTM_Lineseg.py)

Even though you never need to declare a main function, you can test to see if you are in one