Saturday, December 3, 2016

Objects with Functions in Python

I've learned the hard way that using classes makes programming much easier to work with. I had developed a habit of not creating classes when I make a function. While this can be useful for a simple program, I ran into difficulties when I would attempt to import functions from other py files. Building classes makes this process much easier.

A typical example of a class from an introductory book does not make clear the uses of classes and objects instantiated from them. Consider this Cat class that I have made:

# cat class

class Cat():
    def __init__(self, name, color):
        self.name = name
        self.color = color
    def helloKitty(self):
        print("My name is " + self.name + ". I am a " + self.color + " cat.")
    
    def petCat(self):
        print(self.name + " purred. This cat likes when you pet it.")

cat = Cat(name = "Milo", color = "orange")

cat.helloKitty()
cat.petCat()

Running this will return:

runfile('C:/Users/James/Google Drive/Python Scripts/Lessons/CatObject.py', wdir='C:/Users/James/Google Drive/Python Scripts/Lessons')
My name is Milo. I am an orange cat.
Milo purred. This cat likes when you pet it.

What do we get from this? Well, the basic pieces are present. We have a class, which includes all indented text beneath the text, "class Cat():". We have two objects that we pass when we call the function, defined in "def __init__(self, name, color):" These will be used when we call the functions "helloKitty()" and "petCat()". To call these functions, it is best if we first instantiate a Cat object. I have called this object, "cat". I call the functions owned  by "cat" by adding a "." and the function name. Thus, cat.helloKitty() and cat.petCat() call the two lines you see above.

Classes like Cat are boring. It doesn't help me to internalize the significance of objects and functions. I have made a class, MathOperations, for this purpose. MathOperations will let you sum, multiply, raise a base to an exponent and multiply a base by 10 to the specified exponent:


# Math Functions

class MathOperations():
    def __init__(self):
        self.num = 0
        
    def add(self, a, b):
        self.num = a + b 
        return self.num
    
    def multiply(self, a, b):
        self.num = a * b
        return self.num

    def power(self, a, b):
        self.num = a ** b
        return self.num
    
    def exp(self, a, b):
        self.num = a * 10 ** b
        return self.num

math = MathOperations()

m = 8
n = 4

add = math.add(m, n)
multiply = math.multiply(m, n)
power = math.power(m, n)
exp = math.exp(m, n)

names = ['add', 'multiply', 'power', 'exp']
array = [add, multiply, power, exp]

for i in range(len(array)):
    print(names[i], str(m), str(n), '\n', str(array[i]))

At the bottom of this file, I create a MathOperations() object and use its function with numbers 8 and 4 (in that order). I want to show what values these numbers yield in conjunction with the functions and organize the results. Final results return:

runfile('C:/Users/James/Google Drive/Python Scripts/Lessons/MathFunctionLesson.py', wdir='C:/Users/James/Google Drive/Python Scripts/Lessons')
add 8 4 
 12
multiply 8 4 
 32
power 8 4 
 4096
exp 8 4 
 80000

Alternately, I can achieve the same output by importing MathOperations from a different file:


from MathFunctionLesson import *


math = MathOperations()

m = 8
n = 4

add = math.add(m, n)
multiply = math.multiply(m, n)
power = math.power(m, n)
exp = math.exp(m, n)

names = ['add', 'multiply', 'power', 'exp']
array = [add, multiply, power, exp]

for i in range(len(array)):
    print(names[i], str(m), str(n), '\n', str(array[i]))


This barely scratches the surface of the topic, but it is more interesting and memorable than Cat.