As a true object-oriented language, Python is a great place tostart learning about OO programming. In this first segment of a two-partarticle, take your Python skills to the next level with a discussion ofclasses and class instances. Practical (and not-so-practical) examplesincluded.
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!