Python Tutorial 3: Modules, Classes & OOP

This Python tutorial covers Python modules, classes and object-oriented programming principles. This includes:

  • Modules: The Big Picture
  • Module Import Syntax
  • Packages
  • Inheritance
  • Classes
  • Exceptions

 

Modules

In Python a Module is the highest-level program organization unit, modules correspond to Python program files. Each file is a module, and modules import other modules to use the names they define. There are 3 important statements in Python that are used to process modules:

import – Lets a client fetch a module as a whole

from – Allows clients to fetch particular names from a module

reload – Provides a way to reload a module’s code without stopping Python

Modules are an easy way to organize components into a system by serving as self-contained packages of variables known as namespaces. All the names defined at the top level of a module file become attributes of the imported module object.

Import

Let’s assume I built a module called function.py and inside this module I defined a function called addition, like so:

Using the import statement I can use this function anywhere on my Pythonpath, even the interpreter.

From

Notice that when you use the import function, you get all top level variables, functions, and classes. So when using an object you have to preface it with the module it comes from to avoid name space collisions. i.e. function.addition(). If you do not want to preface every object you call from the imported module you can use the from statement.

This is also useful if you don’t want all the objects from a specific module but maybe just 1 or 2.

Reload

The reload() built-in function is useful only if the original module is changed after it has been imported. Because modules are only imported once, any changes that occur after the import will not be shown unless a reload() is done.

Let’s say I take my function.py module and add the following code:

I then import function.py into the interpreter and run the function printer.

I then go back and change the variable message to say “Second Version”.

But when I run printer() in the interpreter again it still says “First version”

Note: I could even run the import statement again and the message would not change.

Now, if I reload() the module, the change should go into effect.

 

Packages

In Python, a directory of Python code is said to be a package. You can import a module from a different directory, or package, using the import statement and a path of names separated by periods.

As you can see, this will become very important when importing other Python libraries like Django, Sqlalchemy, or Flask in the future.

However, any directory that is going to be used as a Python package must contain a __init__.py file. This can contain Python code or simply be left blank, but creating a Python module named __init__.py in every Python package creates a hook that allows Python to know where to search for information.

 

Classes and Object-Oriented Programming

In this next section I will attempt to explain Object-Oriented Programming (or OOP) in a “big picture” context. For those unfamiliar with the subject I strongly encourage you to read “OOP: The Big Picture” in Learning Python.

In Python, everything we’ve done up to this point has been object-based; a variable name is assigned to an object, a function is an object and it accepts objects as arguments and returns an object as output, a for loop will iterate through the indexes of an object. However, to truly be object-oriented, our objects have to participate in something called “inheritance hierarchy”.

To support an inheritance hierarchy we use Python’s most fundamental object-oriented tool, the class. Classes are roughly packages, or groups, of functions (methods) that process built-in object types.

Classes and Instances

Classes
– Serve as instance factories. Their attributes provide behavior – data and functions – that is inherited by all the instances generated from them. They are the framework used to construct instances.

Instances
– Represent the concrete items in a program’s domain. Their attributes record data that varies per specific object.

For example, a Class called Person could generate Instances George and Sally.

The distinction between a Class and its Instances is important to understand so that we can talk about Inheritance.

Inheritance

inheritance

 

Object-Oriented Programming, in Python, is built upon the idea of inheritance. In this example, Instance1 of Person, George, has all of the attributes of his instance as well as all the classes above him. We can describe George as an object that is Alive, he can grow, die, and react to his environment, he is also a Person, which means he is self-aware, capable of complex communication and society, and his name is George, social security number 555-55-5555, and his birthday is May 23, 1932.

Another important aspect of inheritance is that each attribute can be overridden. In instance1 of Animal you will notice that the attribute “society” is set to “complex” which overrides the attribute “society” in the class Animal. When Python searches for an attribute, it will start with the instance that it is in and work its way up to the sub-class and then the super-classes. If there are multiple super-classes it will search from left to right.

Note: A Super Class is just a Class that is higher up in the inheritance hierarchy structure. A Sub Class is just a Class that is lower in the hierarchy structure.

Syntax

Now it is time to look at the syntax for creating classes in Python.

Notice that this class, FirstClass, has 2 functions inside of it, functions that are part of classes are called methods, they behave like any other function except they are defined inside of a Class.

Next we call the class and then assign it to a variable, “x” and “y” are now instances of the class FirstClass().

We can now call the methods assigned to the class FirstClass, note that Python will FIRST look for the method, setdata, in the instance, but since neither “x” nor “y” have a method called setdata or a variable called data then it looks in the class.

Now we can call the display() method to display the variable data, which we set with the previous method, setdata.

To show that an instance really is its own, concrete object we can change the variable data, without using any of the methods available in the class.

Now we can create a second class that is a sub class to FirstClass.

Notice that we are assigning FirstClass as the super class by putting it in the parenthesis of SecondClass. If you have multiple super classes the order in which you list them in the parenthesis is very important. Python will always search for attributes in super classes starting with the super class on the left and moving to the right.

Also notice that the only method we created in SecondClass is called __init__, you will find this method quite commonly within class definitions in Python. It allows you to do many things whenever the class is initialized. In this case we are setting a default value to self.data.

We have now created an instance z and assigned it to SecondClass(), notice that z is pulling a default value for the variable data from SecondClass but using the display() method from FirstClass.

This is a very basic and simple example of object-oriented programming in Python but it is the basis for a very powerful system of object representation. For a deeper dive I recommend reading the chapters on Classes and Inheritance in Learning Python.

 

Exceptions

An Exception is an event that can modify the flow of control through a program; they are triggered automatically on errors, and can be triggered and intercepted by your code. There are 5 statements that we can use to process exceptions.

try/except

Catch and recover from exceptions raised by Python or you.

First we define a function that returns the index of object that is passed in as an argument.

Then we define a string and call our fetcher function

If our arguments our not within the bounds of the object’s index, we get an error

The “try/except” statement allows us to customize this error message. We can catch this error and customize it like so:

try/finally

Perform cleanup actions, whether exceptions occur or not.

First we put our try statement inside of another function called catcher.

You will notice the finally statement will execute at the end of the try statement regardless of whether an exception was hit or not, in this way, it is similar to the else statement at the end of a loop. Also, the program will continue to execute after the try statement has ran as shown in the print statement “continues to execute program after try statement”.

try/else

Run if no exceptions raised.

The else statement is used here in its more traditional statement, to perform an action if the exception does not get tripped.

assert

Conditionally trigger an exception in your code.

raise

Trigger an exception manually in your code

 

Exercises

  1. Create a class called “Parent”, create the following attributes and give them the following default values using the __init__ method:
    1. name = ‘John Smith’
    2. eyeColor = ‘blue’
    3. hairColor = ‘brown’
    4. education = ‘Master’s Degree’

Then make a display() method that displays all of these attributes. Save this class to a file to create a module.

  1. Import your “Parent” class from your module using the from, import. Create a sub-class called “Child” with “Parent” as its super-class. Override the following attributes from “Parent” with these values.
    1. name = “Jeff Smith”
    2. education = ‘High School Diploma’

Do not include the eyeColor or hairColor attributes in the “Child” sub-class. Do not make a display() method.

Next generate an instance of the “Parent” class and an instance of the “Child” class
– Set the eyeColor and hairColor of the “Child” instance in the actual instance
(i.e. “instancename”.eyeColor = “brown”, “instancename”.hairColor =”blonde”)
– Using the display() method, display all of their attributes.

 

Review

Go Back to Part 1 of this Python Tutorial: Types & Operations.

Go Back to Part 2 of this Python Tutorial: Statements, Syntax & Functions.

Python Tutorial 2: Statements, Syntax & Functions

This Python tutorial covers basic Python statements, syntax and functions. This includes:

  • Introducing Python Statements
  • Assignment, Expressions and print
  • if Tests
  • while and for loops
  • Function Basics
  • Scope
  • Advanced Function Topics

 

Print

We have already encountered this statement before; it is used simply to display objects.

print statements automatically put a line feed at the end of each statement; to suppress this line feed put a comma at the end of the statement.

 

if/elif/else

if tests always check for a Boolean true or false, with numbers, 1 is always true and 0 is always false, so a simple if statement would look like this:

This statement is asking, does 1 equal the Boolean equivalent “true”? Of course 1 will ALWAYS equal true and 0 will always equal false. For strings, true is equivalent to a non-null value and false would be a blank or null string.

 

while and for Loops

while Loop

A while loop is the most general iteration construct in the Python language; it simply repeatedly executes a block of code as long as the test at the top of the loop evaluates to true.

A while loop would be the best way to go if there is no predetermined number of occurrences. There are 4 key statements that can be used in loops to help determine the path that they take:

  • break
    • Jumps out of the closest enclosing loop
  • continue
    • Jumps to the top of the closest enclosing loop
  • pass
    • Does nothing at all, an empty placeholder
  • else
    • Runs after the last iteration of the while loop as long as no breaks were hit

The last time through, x equaled 0 so the while loop ended and went to the else statement.

for Loop

The for loop is a generic sequence iterator, it can step through strings, lists, tuples, and other built-in iterables. It uses the same 4 loop control statements that the while loop does:  break, continue, pass, else.

A for loop’s syntax looks like this:

for <target> in <object>

where <target> is a variable name that represents an indexed object and <object> is a predefined, iterable object

To compare two lists to each other, you can use a nested for loop.

Remember that break escapes us from the inner for loop as soon as a match is found, then we check the next key from the outer for loop, it we never hit the break then the key was not found so we print the else clause.

 

Function Basics

Functions are the simplest way to package logic you may wish to use in more than one place and more than one time. Python functions are written with a new statement, def. def creates an object and assigns it to a name.

Syntax:

def executes at runtime, in other words, a function does not have to be fully defined before a program runs.

 

Remember that Polymorphism in Python does not restrict this function to only performing multiplication, it will also perform repetition.

In the second example of the for loop we wrote a nested for loop to determine if there were any matches between a key and a list of items. With a function, this can be done and reused for any 2 sets of data.

This function, intersect, takes in 2 arguments and compares each index of the first argument to each argument of the second, it then appends matching indexes to a list and returns the value. You will notice that the arguments are another example of Polymorphism, the first one is a list and the second one is a tuple but they can still be compared because they are both sequences of data.

 

Scope

In Python, scope can be boiled down to one rule, the LEGB Rule:

Built-in (Python)
Names preassigned in the built-in names module: open, range, SyntaxError…

Global (module)
Names assigned at the top-level of a module file, or declared global in a def within the file.

Enclosing function locals
Names in the local scope of any and all enclosing functions (def or lambda), from inner
to outer.

Local (function)
Names assigned in any way within a function (def or lambda), and not declared
global in that function.

Variables within a function are local variables and cannot be accessed outside of that function unless the variable is defined as “global” before it is used.

 

Function Design Concepts

When designing functions keep in mind that all good functions should be well thought out; for example, every task should be decomposed into purposeful functions (cohesion), and every function should have a clear manner in which it communicates with everything outside of it (coupling). Use the following as general rules-of-thumb:

  • Coupling: use arguments for inputs and return for outputs.
  • Coupling: use global variables only when truly necessary.
  • Coupling: don’t change mutable arguments unless the caller expects it.
  • Coupling: avoid changing variables in another module file directly.
  • Cohesion: each function should have a single, unified purpose.
  • Size: each function should be relatively small.

 

Exercises

  1. First write a while loop that displays even numbers less than or equal to 10, then write the same loop using a for loop. Hint: make a list for the “for” loop.
  2. Define a function that takes in a string and wraps it in the html “<p></p>” tags. Then execute and display it with the string “Hello World”.

 

Next Up

Once you feel like you have mastered Python Statements, Syntax and Functions, Proceed to Part 3 of this Python tutorial: Modules, Classes & OOP.

Or, if you need a refresher, Go Back to Part 1 of this Python Tutorial: Types & Operations.

Python Tutorial 1: Types & Operations

This first Python tutorial will cover the basic types and operations that form the building blocks of the Python syntax. These types in Python can be defined as:

  • Strings
  • Numbers
  • Lists
  • Dictionaries
  • Tuples
  • Files

 

Strings

  • Strings assume a positional ordering among items
  • You can verify the length of a string with the built in function len()
  • You can fetch components of a string with X[position]

You can also use slicing to extract a piece of a string. Slicing extracts a section of a string instead of an individual character.

This general form X[I:J] means “give me everything in X from offset I up to but NOT including offset J.”

In a slice, the left bound defaults to zero, and the right bound defaults to the length of the string.

Strings support repetition and concatenation

Notice that the plus sign (+) and asterisk (*) do different things for different objects, for strings they represent concatenation and repetition, for numbers they represent addition and multiplication. This is a general property of Python called Polymorphism which will be discussed later on.

Also notice that in these previous operations we did not change the original string; that’s because strings are immutable– They cannot be changed after they are created. Every string operation is defined to produce a new string as its result.

To embed a quote in a string, you can “escape” the quote with a backslash.

An escape sequence always begins with a backslash followed by a character that represents what you would like to do. For example, “\n” is a new line “\t” is a horizontal tab and “\’” is an apostrophe.

To convert a string to a number and a number to a string you must use conversion tools, specifically, int() and str().

If you try and add a string and an integer together you get the error above.

If you convert s to an integer then the plus sign performs addition giving the sum 43. Conversely, if you convert i to a string then the plus sign concatenates the string to ‘421’.

 

Numbers

Python supports the standard object types for numbers: integers (whole numbers), floating-point numbers (include decimal point), as well as several more obscure types (long numbers, fixed precision…)

Python supports the standard mathematical operations: +, – , *, /, and ** for exponent.

The “L” at the end of the last number represents Python converting up to a long integer format to try and provide extra precision.

 

Lists

In Python, Lists are “positionally ordered collections of arbitrarily typed objects, and they have no fixed size.”  Unlike strings, Lists are mutable; they can be modified in-place by assignment to offsets. Lists are characterized by brackets with each list item separated by a comma.

We can perform a lot of the same actions on lists as strings. i.e. index, slice, concatenate…

If we want to add another list item to a list, we have to use append() to automatically add a list item to the end of the current list.

Other list operations include sort() (sorts list alphabetically), reverse() (reverses the order of the list), and pop() (removes a list item at a certain index)

Lists also support nesting which allows Lists to be used to represent multi-dimensional matrices.

 

Dictionaries

Up to this point the object types we have learned about have been sequences because they index from left to right. When you want to look at a specific instance in a sequence you call it by its position in the index. Dictionaries are the only core Python object that are not sequences; Dictionaries are known as mappings because they map a key to a value in a Dictionary.

Notice that a Dictionary is syntactically notated with curly braces and key-value pairs with a colon in between.

With Dictionaries it is good practice to perform an audit check on the existence of a key before performing an action on that key. This will prevent an ugly system error and instead, provide a Boolean true or false. This can be done with the built-in function, has_key().

Alternatively, using the  get()  function allows you to set a default answer  if the key does not exist.

Dictionaries also use the same pop() function as lists to delete a key-value pair, the only difference is that you provide a key to delete instead of an index location.

 

Tuples

Tuples (pronounces “tuhple” or “toople”) are exactly like a list except they are immutable, they cannot be changed. They are created syntactically with parenthesis instead of brackets and are only useful if you need to pass information that must remain constant, for data integrity.

 

Files

File objects are Python’s main interface to external files on your computer. There is no specific literal syntax to call a File object, instead you use the built in function open(). When calling this function you pass 2 things, the filename and the action to perform on that file.

 

Exercises

  1. Define a string ‘S’ of four characters where S = ‘spam’. Write an assignment that changes the string to ‘slam’, using only slicing and concatenation.
  2. Make a dictionary with key-value pairs for your first and last name, your favorite color, a hobby you enjoy, and your favorite food. Then write your dictionary to a new text document (.txt) called “myInfo” in the following format:

My Info
First Name: Blah
Last Name: Maxwell
Favorite Color: Green
Hobby: Eating snow
Favorite food: Anchovies

 

Next Up

Once you have a firm understanding of Python Types & Operations, Proceed to Part 2 of this Python tutorial: Statements, Syntax & Functions.