Saturday 16 April 2016

Classes 5: Inheritance

The key defining feature of any object orientated programming language is the concept of inheritance. Just as you and I can inherit property, cash or genetic traits from our parents, grandparents and other ancestors. Python objects like classes can inherit attributes, properties and methods from their ancestors. Which also includes any built in object.

The following examples will show how the basic mechanics of inheritance currently work in Python 3.x.x. The first example simply shows a child class inheriting a method from a parent class. The critical lesson to learn here is the manner in which we tell the Python interpreter that we want the child class to inherit this method in the first place.

Note that the syntax, the manner in which we write the code, is exactly the same as when we define a parameter Python should expect to be passed to a function or method. So there is nothing especially new or difficult to get to grips with here. When it comes time to call the inherited method however. We don't reference the parent. We only ever reference the child as though the method was defined as part of the child class from the get go.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 1 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the parent class. It contains 1 method.
class parentClass():
        def parentMessage(self,text):
                print(text)
                
# Define the child class. It contains no methods, attributes or properties.
class childClass(parentClass):
        pass

# Main Program and Global Variables.
child = childClass()
child.parentMessage("Text is printing from parent.")

Most people however have 2 parents. And in Python our child class can also have 2 parents. In fact it can have a lot more than 2. The second example shows this concept of inheritance from multiple parent classes.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 2 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the parent classes. They contain 1 method each.
class fatherClass():
        def fatherMessage(self,text):
                print(text)

class motherClass():
        def motherMessage(self,text):
                print(text)
                
# Define the child class. It contains no methods, attributes or properties.
class childClass(fatherClass,motherClass):
        pass

# Main Program and Global Variables.
child = childClass()
child.fatherMessage("Text is printing from father.")
child.motherMessage("Text is printing from mother.")

Just as in real life. This ancestral linage of our child class does not stop with it's parent classes. If the father class inherits a method, attribute or property from a grandfather class. Then so too will the child class. As is shown in example 3.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 3 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the ancestor classes. They contain 1 method each.
class grandfatherClass():
        def grandfatherMessage(self):
                print("This text is printing from grandfatherMessage().")

class fatherClass(grandfatherClass):
        def fatherMessage(self):
                print("This text is printing from fatherMessage().")
                
# Define the child class. It contains no methods, attributes or properties.
class childClass(fatherClass):
        pass

# Main Program and Global Variables.
grandfather = grandfatherClass()
father = fatherClass()
child = childClass()

print("\ngrandfather:")
grandfather.grandfatherMessage()

print("\nfather:")
father.grandfatherMessage()
father.fatherMessage()

print("\nchild:")
child.grandfatherMessage()
child.fatherMessage()

There are however occasions when inherited features need to be overridden. Creating a new class based on an existing class can save us a lot of time and code. This makes our program more efficient since we get to reuse code in much the same way we can reuse functions. However we might need to override an inherited method because it doesn't do exactly what we need it to do.

Python allows us to do this simply by redefining the method at the point in the ancestral lineage where we wish the new version of the method to take effect. In the fourth example below. We override the method we inherited from the grandfatherClass within the childClass.

By doing this we don't need to redefine the entire grandfatherClass. Which means the fatherClass and any objects based on it alone will be unaffected as will any objects based on the grandfatherClass.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 4 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the ancestor classes. They contain 1 method each.
class grandfatherClass():
        def grandfatherMessage(self):
                print("This text is printing from grandfatherMessage().")

class fatherClass(grandfatherClass):
        def fatherMessage(self):
                print("This text is printing from fatherMessage().")
                
# Define the child class. It has 1 method to override grandfatherMessage(self).
class childClass(fatherClass):
        def grandfatherMessage(self):
                print("The child has overridden the grandfather!!!")

# Main Program and Global Variables.
grandfather = grandfatherClass()
father = fatherClass()
child = childClass()

print("\ngrandfather:")
grandfather.grandfatherMessage()

print("\nfather:")
father.grandfatherMessage()
father.fatherMessage()

print("\nchild:")
child.grandfatherMessage()
child.fatherMessage()

Inheritance and the ability to override things presents us with a problem however. There is nothing stopping us from defining attributes, properties or methods with the same name in each of the classes we create. This means the names of inherited class members can come into conflict. Many developers assign common names to common functions. But the code within will all be written slightly differently to produce different outcomes. To make sure our programs behave as we expect them to, Python has a set of rules. These rules dictate how Python searches through the ancestral lineage to find the inherited class member.

It should become clear from the next two examples that Python will search top to bottom and left to right. In other words Python will search through the entire lineage of the left-most parent class stated in our child class definition before moving onto the next parent.

In the case of our example that means searching the lineage of fatherClass for the parentMessage() method before moving onto motherClass. And since it will find this method in the grandfatherClass, it will use this version of the method.

Another interesting point to note here is that grandfatherClass is an ancestor of fatherClass. But not motherClass.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 5 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the ancestor classes. They contain 1 method each.
class grandfatherClass():
        def grandfatherMessage(self):
                print("This text is printing from grandfatherMessage().")

class fatherClass(grandfatherClass):
        def parentMessage(self):
                print("From fatherClass():")
                print("This text is printing from parentMessage().")

class motherClass():
        def parentMessage(self):
                print("From motherClass():")
                print("This text is printing from parentMessage().")
                                
# Define the child classes. They contain no methods, attributes or properties.
class child1Class(fatherClass,motherClass):
        pass

class child2Class(motherClass,fatherClass):
        pass

# Main Program and Global Variables.
grandfather = grandfatherClass()
father = fatherClass()
mother = motherClass()
child1 = child1Class()
child2 = child2Class()

print("\ngrandfather:")
grandfather.grandfatherMessage()

print("\nfather:")
father.grandfatherMessage()
father.parentMessage()

print("\nmother:")
mother.parentMessage()

print("\nchild1:")
child1.grandfatherMessage()
child1.parentMessage()

print("\nchild2:")
child2.grandfatherMessage()
child2.parentMessage()

If we switch the order fatherClass and motherClass are passed to childClass. We can see that Python will now search for the parentMessage() method in motherClass first. And therefore use the motherClass version of that method.

#!/usr/bin/env python3

__project__= "Python Classes: Inheritance"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 6 $"
__date__ = "$Date: 2016/04/14 22:06:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Define the ancestor classes. They contain 1 method each. Except for
# fatherClass(). It inherits everything from grandfatherClass().
class grandfatherClass():
        def grandfatherMessage(self):
                print("This text is printing from grandfatherMessage().")

        def parentMessage(self):
                print("From grandfatherClass():")
                print("This text is printing from parentMessage().")

class fatherClass(grandfatherClass):
        pass
        
class motherClass():
        def parentMessage(self):
                print("From motherClass():")
                print("This text is printing from parentMessage().")
                                
# Define the child classes. They contain no methods, attributes or properties.
class child1Class(fatherClass,motherClass):
        pass

class child2Class(motherClass,fatherClass):
        pass

# Main Program and Global Variables.
grandfather = grandfatherClass()
father = fatherClass()
mother = motherClass()
child1 = child1Class()
child2 = child2Class()

print("\ngrandfather:")
grandfather.grandfatherMessage()
grandfather.parentMessage()

print("\nfather:")
father.grandfatherMessage()
father.parentMessage()

print("\nmother:")
mother.parentMessage()

print("\nchild1:")
child1.grandfatherMessage()
child1.parentMessage()

print("\nchild2:")
child2.grandfatherMessage()
child2.parentMessage()

Sunday 10 April 2016

Classes 4: Encapsulation

Encapsulation can be a bit of a sticky subject. Many people have strong views on the subject and others just don't care. But what is it? Basically it is two distinct but related concepts. We can make class members like attributes private or protected. This stops anything outwith the class from accessing those members directly. We can also bundle data with its associated method. Which we did in Classes 3: Properties.

When we decide to make a class member like an attribute private. We have basically made the decision that it must be protected from the outside world. And this I think is the biggest problem with the whole concept when we have direct access to the source code. Nothing is really protected because with direct access to the source code. We can change whatever we want.

For this reason it is better to think in terms of a compiled program or library that might be shared with many people outside your organisation. Normally an outsider would access your class using the documented API. An analogy might be a customer at a bank.

A bank is a class of business. An attribute of a bank is that it holds customer accounts. Each account has a value. The amount of cash associated with the account. Account attributes of bank classes are however private. The method we use to access the account's value is the clerk. The clerk is the getter. If we give the clerk the correct information, which is different for every customer account and thus variable, the clerk will return the value of the account. We get our money.

We can put this analogy into action with the following example. After we create accounts for Bob and Sue with the bank class, the only way to access those accounts is through clerk method. All of the attributes are private.

#!/usr/bin/env python3

__project__= "Python Classes: The Bank Example"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 1 $"
__date__ = "$Date: 2016/04/11 15:23:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Create the bank class.
class bank:
        # Initialise bank with custom attributes.
        def __init__(self,account,pin,cash):
                # This is a bank. So all attributes are private.
                self.__account = account
                self.__pin = pin
                self.__cash = cash
                
        # Create the getter method.
        def clerk(self,account,pin):
                if account == self.__account:
                        if pin == self.__pin:
                                return str(self.__cash) # We get our money.
                        else:
                                return "CALLED THE COPS!!!" # Wrong pin code.
                else:
                        return "no such account" # Wrong account number.

# Global variables
bobsAccount = bank(12345678,9990,500)
suesAccount = bank(87654321,2204,5)

# We can ask the clerk how much money Bob and Sue have.
print("Bob has " + bobsAccount.clerk(12345678,9990) + " in the bank.\n\n")
print("Sue has " + suesAccount.clerk(87654321,2204) + " in the bank.\n\n")

# Sue forgot her pin code and used Bob's instead.
print("Sue has " + suesAccount.clerk(87654321,9990) + " in the bank.\n\n")

# Bob can't remember his account number.
print("Bob has " + bobsAccount.clerk(12945070,9990) + " in the bank.\n\n")

# Uncomment the following code to prove the attributes are private.
# print("Bob has " + str(bobsAccount.__cash) + " in the bank.\n\n")

The Big Lie
Uncommenting the last line of code in the example seems to prove the attributes of bank are indeed private. But this is not actually the case. Everything in Python is public. We just need to know where to look.

Every Python object has a number of built-in attributes and methods that are added automatically. The method __init__() is one such example. This method runs automatically every time an instance of a class is created. When we define __init__() in our code, we are overriding the default. And this allows us to add a degree of flexibility to the attributes, properties and methods we have add to the class.

All of the attributes within a class are contained within a dictionary object called __dict__. As we've seen in the Electronic Point Of Sale project. Dictionary objects can be accessed in much the same way as lists. And this means a determined developer would have no real problem in finding and interrogating private attributes within a class.

To get around this problem, supposedly, we can override the built in getters and setters that all Python classes have. These are called __getattr__ and __setattr__ respectively. However I've never seen this working and don't seem to be able to make it work. So, so far as I'm concerned for the time being. It doesn't work (at least not without crashing your program) and everything is public. Even when it's private.

Reading The Dictionary

#!/usr/bin/env python3

__project__= "Python Classes: The Bank Example"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 2 $"
__date__ = "$Date: 2016/04/11 20:27:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

# Create the bank class.
class bank:
        # Initialise bank with custom attributes.
        def __init__(self,account,pin,cash):
                # This is a bank. So all attributes are private.
                self.__account = account
                self.__pin = pin
                self.__cash = cash
             
# Global variable. Bob creates his account with the bank.
bobsAccount = bank(12345678,9990,500)

# Lets look at the dictionary.
print("\n\nReading the whole dictionary")
print(bobsAccount.__dict__)

# Now lets search for the cash.
d = bobsAccount.__dict__ # This will make the dictionary easier to work with.
for key in d.keys():
        # Search for the keyword cash and do something.
        if "cash" in key:
                print("\n\nCash found in " + key)
                print(key + " = " + str(d[key]))
             
                # We can even edit the value of the attribute.
                print("\n\nLets give Bob more cash!!!")
                d[key] = 1000
                print(key + " = " + str(d[key]))              
                break
        else:
                print("\nCash not found in " + key)
             
# Now lets prove we actually altered Bob's account.
# Since we know the name of the attribute. We can access it directly.
print("\n\nCash in Bob's account = " + str(bobsAccount._bank__cash))

Why Bother Then?
There are a few reasons. The straw man is that it's what developers from the likes of Java or C++ backgrounds have been taught to do. So it's considered "good practice". However it would also be good practice if people just read the API reference, used the class properly and saved other programmers from having to write countless lines of extra code.

A much better reason is that it ensures there is one and only one obvious means of accessing and altering class members. Which in turn helps to bolster the integrity of those class members and the stability of the program overall. By using encapsulation with getters and setters, we can validate data being passed around the program. Everything in theory happens in an orderly and predictable way.

Clearly this isn't a massive problem with very small and simple examples. But when a program runs into hundreds, thousands or even millions of lines of code, passes through the hands of dozens of programmers. It becomes a problem.

Saturday 9 April 2016

Classes 3: Properties

Properties are the Pythonic way of implementing class members with associated getters and setters. In other object oriented languages like Java this is done from the beginning. In Python, the convention is to use getters and setters only when they are actually needed. For example when exception handling is required or when it becomes desirable to make a class member private. Otherwise the convention is to use the simplest implementation.

We can see the use of properties, getters and setters in action by modifying our bicycle example as follows.
#!/usr/bin/env python3

__project__= "Python Classes: The Bicycle Example"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 3a $"
__date__ = "$Date: 2016/04/10 01:48:00 $"
__copyright__ = "Copyright (c) 2016 Kevin Lynch"
__license__ = "GPLv3"

class bicycle: # Defines the bicycle class.
        # Initialise bicycle with custom attributes.
        def __init__(self,frame,wheels):
                self.frameSet = frame
                self.wheelSet = wheels
                
        @property # Property decorator.
        def frameSet(self):
                return self.__frameSet

        @frameSet.setter # Setter method for the property frameSet.
        def frameSet(self,frame):
                if frame == "carbon":
                        self.__frameSet = frame
                elif frame == "steel":
                        self.__frameSet = frame
                else:
                        self.__frameSet = "wood"

        @property # Property decorator.
        def wheelSet(self):
                return self.__wheelSet

        @wheelSet.setter # Setter method for the property wheelSet.
        def wheelSet(self,wheels):
                if wheels == "carbon":
                        self.__wheelSet = wheels
                elif wheels == "alloy":
                        self.__wheelSet = wheels
                else:
                        self.__wheelSet = "wood"

# Global variables. Both reference the bicycle class.
bobsBike = bicycle("carbon","carbon")
suesBike = bicycle("steel","alloy")

print("Bob's Bike:\nFrame Set: " + bobsBike.frameSet + "\nWheel Set: " + bobsBike.wheelSet)
print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

# We can still change things as before.
suesBike.frameSet = "plastic"

print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

The only thing we have had to change in our bicycle example is the implementation of the bicycle class. In particular we have added our getters and setters. The getter method is decorated with the @property decorator and the setter method is decorated with the @<property name>.setter decorator. The rest of the program is unchanged.

This means that when we implement an attribute within a class in the simplest way possible. We can then change that implementation later without breaking the whole program. We use the same syntax to access properties as we do when accessing attributes or methods.

Classes 2: __init__(self)

The code from Classes: Part 1 is just a simple introduction to classes. While the code does work, it could be more flexible and better defined. For example it would be more efficient if we could add the individual specifications for both Bob and Sue's bikes when the object instances are created. To do this we use the __init__(self) method to initialise the object instance with the correct values for each attribute.

We can see how this works with the following code.

#!/usr/bin/env python3

__project__= "Python Classes: The Bicycle Example"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 2 $"
__date__ = "$Date: 2015/11/21 21:19:00 $"
__copyright__ = "Copyright (c) 2015 Kevin Lynch"
__license__ = "GPLv3"

class bicycle: # Defines the bicycle class.
        # Initialise bicycle with custom attributes.
        def __init__(self,frame,wheels):
                self.frameSet = frame
                self.wheelSet = wheels

# Global variables. Both reference the bicycle class.
bobsBike = bicycle("carbon","carbon")
suesBike = bicycle("steel","alloy")

print("Bob's Bike:\nFrame Set: " + bobsBike.frameSet + "\nWheel Set: " + bobsBike.wheelSet)
print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

# We can still change things as before.
suesBike.frameSet = "plastic"

print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

For such a small program __init__(self) may seem redundant. However getting to grips with this basic concept will make working with objects and classes much easier in larger programs.

Friday 8 April 2016

Classes 1: A Very Simple Introduction

#!/usr/bin/env python3

__project__= "Python Classes: The Bicycle Example"
__author__ = "Kevin Lynch"
__version__ = "$Revision: 1 $"
__date__ = "$Date: 2015/11/21 21:19:00 $"
__copyright__ = "Copyright (c) 2015 Kevin Lynch"
__license__ = "GPLv3"

class bicycle: # Defines the bicycle class.
frameSet = "carbon"
wheelSet = "alloy"

# Global variables. Both reference the bicycle class.
bobsBike = bicycle()
suesBike = bicycle()

print("Bob's Bike:\nFrame Set: " + bobsBike.frameSet + "\nWheel Set: " + bobsBike.wheelSet)
print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

# Sue's bike is defferent from Bob's. So we can change it.
suesBike.frameSet = "steel"

print("\n\nSue's Bike:\nFrame Set: " + suesBike.frameSet + "\nWheel Set: " + suesBike.wheelSet)

Wednesday 29 July 2015

Electronic Point of Sale


Since I was getting bored with strings and the basics. I decided to take a fun little project. The challenge is to write a program that works like an electronic point of sale. In simpler terms a cash register.

The code gets a little messy because I was getting tired and frustrated and I'm not a programmer of any level of skill. Although I have Python 3.4 installed on my PC. Python 2.7 is used by default. Which it turns out is terrible at handling unicode characters. All I wanted it to print was the £ sign in a raw_input() prompt. The answer was to explicitly use Python 3.x.

With the unicode problem sorted and the program re-factored for Python 3.x I decided to call it a day with what I have for now. Back to basics again I think.


  • The program assumes a terminal with of 80 columns. Which used to be the norm.
  • The database of goods is a simple dictionary. Which actually works quite well for this application.
  • To select an item from the inventory simply type it in.
  • Only one item can be selected at a time. But you can allow the program to loop several times to build up a list of items.
  • An item can appear more than once in your list.
  • When you select "P" to pay. The program will ask how much you are paying and then calculate your change. If you don't give enough, you'll be told to come back when you can pay.
  • The program will pause for a few seconds to allow you to read the receipt. And then it moves on to the next customer.
  • Press "Q" to quit.


#!/usr/bin/env python3

# Project       : Electronic Point of Sale
# Author        : Kevin Lynch
# Created      : 29.07.2015

# Brief: Create a program that will hold a database of goods matched against
#        their prices which can then be used to tally up the cost of a shoppers
#        order.

# Function definitions.
def wait(t):
        for i in range(0,t):
                i = i + 0
                
def orderScreen(s): # Show goods for sale with prices.
        welcome = " Welcome to Python General Stores "
        instruct = "[P = Pay] [Q = Quit] | Please select an item."
        print("{:*^80}".format(welcome))
        
        for key in s.keys():
                print(u"{: >39} \xA3{: <39.2f}".format(key,s[key]))
                
        print("{:*^80}".format(""))
        print("{: ^80}".format(instruct))
        print("{:*^80}".format(""))

def acceptPayment(o,s):
        import time
        header = " Sale "
        prompt = u"{: >40}\xA3".format("Amount Given: ")
        total = 0.00
        given = 0.00
        change = 0.00
        
        for i in range(0,len(o)): # Calculate total due.
                for key in s.keys():
                        if o[i] == key:
                                total = total + s[key]
        
        print("{:*^80}".format(header)) # Print order and amount due.
        
        for i in range(0,len(o)):
                print(u"{: >39} \xA3{: <39.2f}".format(o[i],s[o[i]]))
                
        print(u"{: >40}\xA3{: <39.2f}".format("Amount Due: ",total))
        given = float(input(prompt)) # Amount given.
        if given >= total: # Calculate change due.
                change = given - total
                print(u"{: >40}\xA3{: <39.2f}".format("Change Due: ",change))
        else:
                print("{: ^80}".format("Please come back when you can pay."))
        time.sleep(3)

def takeOrder(s): # Get the customers order.
        kbd = ""
        order = []
        while str.upper(kbd) != "P": # Loop until customer decides to pay.
                if str.upper(kbd) == "Q": # Break loop to quit.
                        break 
                orderScreen(stock)
                kbd = input("::")

                for key in s.keys():
                        if key == str.capitalize(kbd):
                                order.append(str.capitalize(kbd))
                        
        if str.upper(kbd) == "P":
                acceptPayment(order,stock) # Call acceptPayment
                
        return kbd # Return to main program.

# Global variables.
stock = {"Apple":0.50,"Banana":0.50,"Milk":1.00,"Bread":1.50,"Bacon":5.60}

# Main Program
kbd = ""
while str.upper(kbd) != "Q":
        kbd = takeOrder(stock)

Tuesday 28 July 2015

Arithmetic Operators

#!/usr/bin/env python

# Like most languages Python supports some basic arethmetic operators.
# + Addition
# - Subtration
# * Multiplication
# / Division
# // Explicite "floor/integer division"

# % Calculates the remainder of a division.
# ** Calculates powers
# () Brackets are also supported for grouping. Think BODMAS theory.

number = 0 # Set number to 0.
print number

number = number + 10 # number is now 10.
print number

number = number - 3 # number is now 7.
print number

number = number * 3 # number is now 21.
print number

number = number / 7 # number is now 3.
print number

number = number // 2 # number is now 1.
print number

number = number % 2 # number is now 1.
print number

number = 0
number = (((((number + 10) - 3) * 3) / 7) // 2) % 2 # number is now 1.
print number

number = 0
number = number + 10 - 3 * 3 / 7 // 2 % 2 # number is now 10.
print number

number = number ** 2 # number is now 100.
print number