Python Tales - The Python Tutor Blog

A Python Programming Blog, from a Pythoneer to Pythoneers, created by The Python Tutor.

Friday, July 21, 2017

A Python Tale on Object Oriented Programming (Part I)

Hello my friends, today's entry is going to be about Object Oriented Programming with Python, we are going to program an abstraction of a simple Clock in Python, in such a way we can understand the importance and convenience on why you should program in the Object Oriented Paradigm, and why you should do it with Python.  So let's start by talking a little bit about Object Oriented Programming.
Accordantly to the Wikipedia, "Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which may contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods."
This is in fact the structure of an object, but doesn't state so much on why does this exists? Well in the nature and also in the mankind created world, there is an intrinsic structure, some kind of organization, in such a way that you can abstract anything in the world with these same constructs, data and procedures, any animal, vegetal or thing (objects) in the real world, can be abstracted to data and procedures, data is the information that you can get from physical features of the object and actions made are the procedures that you can get from the object itself, these actions can or cannot change the information or data within the object.
The advantages that you might find in Object Oriented Programming, is that your code can become more organized, in such a way that would be in time easier to understand, maintain and modify. Object Oriented Programming comes along with some other properties that you can take advantages in order to gain more complexity so you can design your Objects to fit your needs. But let's peel the onion a layer at a time.

1.     Classes vs Objects


Let's begin with talking about the differences with these two concepts, a Class is the definition for a given type of object, that is the data and procedures contain within the object. Let's say that this is the Skeleton or Design of an object, the internal structure and how it must behave. An Object is a construction of the Class, is also been said that is an instance of a Class, that is a copy of this class assigned to a variable that lives inside the memory. Now let's take a break with theory and start coding a Class as the definition for our Clock.

First we start by abstracting the things (data and procedures) that we need to take into account for our Clock Class. We can be all day discussing about the Clock and how much things we can get from it right? But let's keep it simple, even that the Clock can give up the time with three handles, one for the seconds, one for the minutes, and one for the hours, is not necessary that we construct a data type for each one of this properties, a simpler way is that we can account the seconds from the midnight to the current time, and work all of the other properties based on this, so for now we have one property to abstract and that is the seconds from midnight. But what about the procedures? Well need to construct some functions that we can use to know the hours and minutes, but before we get into that let's talk about a simple procedure to abstract, and that is the ticking process, this process increment the Clock seconds one second at a time. So we have the following as a starter.
Properties
Methods
·         Seconds
·         Tick
Now let's code this in Python with the Class definition.
class Clock(object):

    pass

The very basic first thing to acknowledge is the Python class keyword, with this you can define your Class Name, in this case we call it Clock, and within the round brackets or parenthesis is the Parent Class that we will take for Inheritance. We will cover this later, you can leave this space empty but using the objectkeyword for this, means that we are going also to take the basics built in methods for an object in Python, later we are going to see which ones are those. Now after you code this, you will need to create a definition method, this is the first method used when object is instantiated, you can use this method to initialize the intrinsic data within the objects, because baby dogs are born with sex and color, not a good reference but you get the point.
class Clock(object):
 
    def __init__(self, hours=0, minutes=0, seconds=0):
 
        self.seconds = 0
 
        self.seconds += seconds
        self.seconds += minutes * 60
        self.seconds += hours * 3600

As you can see in this code, this method is call init method with two underscore on each side, this method is a basic function definition, but as for each method, it takes as first parameter the keyword self, which is the reserved keyword used to reference the object itself inside the function, you can use any word here, but the practice recommends for this word to be self, and the Python editor will highlight this for you. After that you can use any amount of parameters to take as inputs in this method, basically you'll need to use them in such a way that is clear when you initialize this object to the real world data. For this example we took as data inside the object as the seconds from midnight, but this is not very clever in terms of real world, because in any time of the day you will not know the exact amount of seconds from midnight but rather the hours and minutes; so for this example we took that same construct, three parameters for each of this data, but inside of the object, this is converted to seconds from midnight.
Something to point out, as you can see, there is a variable called self.seconds, this is also called instance variable, once it is created, this will live within the object and you can get access to it from any method using the same variable name, self.seconds.
An example on how use this is the next code.
>>> clock1 = Clock(6, 24, 15)
>>> clock2 = Clock(13, 56, 2)

2.     Encapsulation


Even that we haven't talk about this, we have covered some about encapsulation, this is a concept in which we gather all the data inside the object itself and how we are going to manipulate this data from the outside, this is something called public interface, if you need to whether initialize or do some other manipulations to the information inside the object, you do it through its own public interface, there are the methods that you need to define for this same purpose. In this way you can get code that is maintainable in time, because if you need to modify you code, you just need to look under the hood and modify without affecting the public interface and its interaction with the outside world.
Let's begin by defining the Tick method of this public interface.
 class Clock(object):
 
    def __init__(self, hours=0, minutes=0, seconds=0):
 
        self.seconds = 0
 
        self.seconds += seconds
        self.seconds += minutes * 60
        self.seconds += hours * 3600
 
    def Tick(self, seconds=1):
 
        self.seconds += seconds

As you can see this method changes the data or property seconds inside the object by incrementing its value by one the value provided as parameter, let's try using this method.
>>> clock1 = Clock(6, 30, 0)
>>> clock1.seconds
23400
>>> clock1.Tick()
>>> clock1.seconds
23401
>>> clock1.Tick(5)
>>> clock1.seconds
23406

In this example we create an Clock object and initialize it with 6 hours and 30 minutes from midnight, also you can see that you can access the property seconds using dot notation, Python will allow you to access in this way but it is not recommended, as practice it is recommended to use a public interface, that is a method to get this value, this is necessary in other languages.
And as you see also the Tick method changes the seconds inside the object, with a value or not provided to this method. Now let's complete this class with a public interface so get or set the value of seconds in a way that means something to the real world.
class Clock(object):
 
    def __init__(self, hours=0, minutes=0, seconds=0):
 
        self.seconds = 0
 
        self.seconds += seconds
        self.seconds += minutes * 60
        self.seconds += hours * 3600
 
    def Tick(self, seconds=1):
 
        self.seconds += seconds
 
    def getHours(self):
 
        return self.seconds // 3600
 
    def getMinutes(self):
 
        return (self.seconds % 3600) // 60
 
    def getSeconds(self):
 
        return (self.seconds % 3600) % 60
 
    def setHours(self, hours):
 
        self.seconds = self.seconds - self.getHours() * 3600
        self.seconds = self.seconds + hours * 3600
 
    def setMinutes(self, minutes):
 
        self.seconds = self.seconds - self.getMinutes() * 60
        self.seconds = self.seconds + minutes * 60
 
    def setSeconds(self, seconds):
 
        self.seconds = self.seconds - self.getSeconds()
        self.seconds = self.seconds + seconds
 
    def setTime(self, hours=None, minutes=None, seconds=None):
 
        if hours != None:
 
            self.seconds += hours * 3600
 
        if  minutes !=  None:
 
            self.seconds += minutes * 60
 
        if seconds != None:
 
            self.seconds += seconds
 
    def getTime(self):
 
        result = (self.getHours(), self.getMinutes(), self.getSeconds())
        return  result
 
    def reset(self):
 
        self.seconds = 0

So this is the entire public interface of the Clock class, as you can see the methods names are very readable, you can infer what these methods do, there are also some useful methods for getting or setting the time in tuples, also with a method for resetting the object. Let's code an example using some of these methods.
>>> clock1 = Clock(9, 30, 0)
>>> clock1.Tick(600)
>>> clock1.getHours()
9
>>> clock1.getMinutes()
40
>>> clock1.setSeconds(15)
>>> clock1.getTime()
(9, 40, 15)
>>> clock1.reset()
>>> clock1.getTime()
(0, 0, 0)

Finally we are going to override a Python Object built-in method, and that is the __str__ which is the one used by the Python print function, the idea of this method is to return a readable representation of the Clock, so let's get into that.
class Clock(object):
 
    def __init__(self, hours=0, minutes=0, seconds=0):
 
        self.seconds = 0
 
        self.seconds += seconds
        self.seconds += minutes * 60
        self.seconds += hours * 3600
 
    # A bunch of methods here
 
    def __str__(self):
 
        return  str(self.getHours()) + ":" + str(self.getMinutes()) + ":" + str(self.getSeconds())

Let's do some examples.
>>> clock1 = Clock(10, 20, 10)
>>> print clock1
10:20:10
>>> clock1.Tick(3600)
>>> print clock1
11:20:10

So we have covered some of the basics of Python Objects so far, but this is not everything, for the second part we will cover the rest of the built-in functions, I hope you have found this entry helpful to you and can now create your own Python objects. So thanks for coming by my new entry and I hope you have enjoyed this as much as I enjoyed writing it, stop by the comments if you want to discuss about this. Don't forget to share this with your Python Peers. Cheers my friends.

Update: You can find the second part of this set of entries in here - A Python Tale on Object Oriented Programming (Part II)