Object Oriented Programming With Python (part 1) - Under Construction (
Page 6 of 6 )
It's also possible to automatically execute a function
when the class is called to create a new object. This is referred to in geek
lingo as a "constructor" and, in order to use it, your class definition must
contain a method named __init()__
Typically, the __init__() constructor
is used to initialize variables or execute class methods when the object is
first created. With that in mind, let's make a few changes to the veryBigSnake
class:
class veryBigSnake:
# constructor
def __init__(self):
# initialize properties
self.name = "Peter Python"
self.type = "python"
print "New snake in da house!"
# function to set snake name
def set_snake_name(self, name):
self.name = name
# function to set snake type
def set_snake_type(self, type):
self.type = type
# function to display name and type
def who_am_i(self):
print "My name is " + self.name + ", I'm a " + self.type + " and I'm
perfect for you! Take me home today!"
In this case, the constructor sets up a couple of variables
with default values and prints a short message indicating that a new object has
been successfully created.
The set_snake_type() and set_snake_name()
functions alter the object's properties, while the who_am_i() function provides
a handy way to see the current values of the object's properties.
Here's
an example of how it could be used:
>>> alpha = veryBigSnake()
New snake in da house!
>>> alpha.who_am_i()
My name is Peter Python, I'm a python and I'm perfect for you! Take me home
today!
>>> alpha.set_snake_name("Alan Adder")
>>> alpha.set_snake_type("harmless green adder")
>>> alpha.who_am_i()
My name is Alan Adder, I'm a harmless green adder and I'm perfect for you!
Take
me home today!
>>>
Since class methods work in exactly the same way as regular
Python functions, you can set up the constructor to accept arguments, and also
specify default values for these arguments. This makes it possible to simplify
the class definition above to:
class veryBigSnake:
# constructor
# now accepts name and type as arguments
def __init__(self, name="Peter Python", type="python"):
self.name = name
self.type = type
print "New snake in da house!"
# function to set snake name
def set_snake_name(self, name):
self.name = name
# function to set snake type
def set_snake_type(self, type):
self.type = type
# function to display name and type
def who_am_i(self):
print "My name is " + self.name + ", I'm a " + self.type + " and I'm
perfect for you! Take me home today!"
And here's how you could use it:
>>> # create two snakes
>>> alpha = veryBigSnake("Roger Rattler", "rattlesnake")
New snake in da house!
>>> beta = veryBigSnake()
New snake in da house!
>>>
>>> # view snake information
>>> alpha.who_am_i()
My name is Roger Rattler, I'm a rattlesnake and I'm perfect for you! Take
me home today!
>>>
>>> # notice that the beta snake has been created with default properties!
>>> beta.who_am_i()
My name is Peter Python, I'm a python and I'm perfect for you! Take me home
today!
>>> alpha.name
'Roger Rattler'
>>> alpha.type
'rattlesnake'
>>> beta.name
'Peter Python'
>>> beta.type
'python'
>>>
It should be noted here that it is also possible to directly
set instance properties, bypassing the exposed methods of the class. For
example, the line
>>> beta.set_snake_name("Vanessa Viper")
>>>
is technically equivalent to
>>> beta.name="Vanessa Viper"
>>>
Notice I said "technically". It is generally not advisable to
do this, as it would violate the integrity of the object; the preferred
technique is always to use the methods exposed by the object to change object
properties.
Just as an illustration - consider what would happen if the
author of the veryBigSnake() class decided to change the variable "name" to
"snake_name".You would need to rework your test script as well, since you were
directly referencing the variable "name". If, on the other hand, you had used
the exposed set_snake_name() method, the changes to the variable name would be
reflected in the set_snake_name() method by the author and your code would
require no changes whatsoever.
By limiting yourself to exposed methods,
you are provided with a level of protection which ensures that changes in the
class code do not have repercussions on your code.{mospagebreak title=Tick,
Tick} Now that you've (hopefully) understood the fundamental principles here,
let's move on to something slightly more practical. This next package allows you
to create different Clock objects, and initialize each one to a specific time
zone. You could create a clock which displays local time, another which displays
the time in New York, and a third which displays the time in London - all
through the power of Python objects. Let's take a look:
# a simple clock class
# each Clock object is initialized with offsets (hours and minutes)
# indicating the difference between GMT and local time
class Clock:
# constructor
def __init__(self, offsetSign, offsetH, offsetM, city):
# set variables to store timezone offset
# from GMT, in hours and minutes, and city name
self.offsetSign = offsetSign
self.offsetH = offsetH
self.offsetM = offsetM
self.city = city
# print message
print "Clock created"
# method to display current time, given offsets
def display(self):
# use the gmtime() function, used to convert local time to GMT
# import required methods from the time module
# returns an array
from time import time, gmtime
self.GMTTime = gmtime(time())
self.seconds = self.GMTTime[5]
self.minutes = self.GMTTime[4]
self.hours = self.GMTTime[3]
# calculate time
if(self.offsetSign == '+'):
# city time is ahead of GMT
self.minutes = self.minutes + self.offsetM
if (self.minutes > 60):
self.minutes = self.minutes - 60
self.hours = self.hours + 1
self.hours = self.hours + self.offsetH
if (self.hours >= 24):
self.hours = self.hours - 24
else:
# city time is behind GMT
self.seconds = 60 - self.seconds
self.minutes = self.minutes - self.offsetM
if (self.minutes < 0):
self.minutes = self.minutes + 60
self.hours = self.hours - 1
self.hours = self.hours - self.offsetH
if (self.hours < 0):
self.hours = 24 + self.hours
# make it look pretty and display it
self.localTime = str(self.hours) + ":" + str(self.minutes) + ":" +
str(self.seconds)
print "Local time in " + self.city + " is " + self.localTime
# that's all, folks!
As you can see, the class's constructor initializes an object
with four variables: the name of the city, an indicator as to whether the city
time is ahead of, or behind, Greenwich Mean Time, and the difference between the
local time in that city and the standard GMT, in hours and minutes.
Once
these attributes have been set, the display() method takes over and performs
some simple calculations to obtain the local time in that city.
And
here's how you could use it:
>>> london = Clock("+", 0, 00, "London")
Clock created
>>> london.display()
Local time in London is 8:52:21
>>> bombay = Clock("+", 5, 30, "Bombay")
Clock created
>>>
>>> bombay.display()
Local time in Bombay is 14:23:5
>>> us_ct = Clock("-", 6, 00, "US/Central")
Clock created
>>> us_ct.display()
Local time in US/Central is 2:53:11
>>>
And that's just about it for the moment. You now know the
basics of Python's object-oriented programming paradigm, and should be able to
construct and use your own objects. While you're doing that, remember that I'll
be back next week with some more dope on the topic - the second part of this
article will cover inheritance, overrides, destructors and the built-in Python
functions that help you navigate between classes and class instances. Don't miss
it!
Note: All examples in this article have been tested on Linux/i586
with Python 1.5.2. Examples are illustrative only, and are not meant for a
production environment. YMMV!