Essential Python Scripting

Note: many examples have been adapted from the python documentation

click here for the programming exercise of 2021

click here for the associated Jupyter notebook

Control Flow

This section briefly introduces common control statements in Python. The control statements are written in the block structure and do not have an end statement. The end of a block is expressed by indentation.

if Statement

The if statement is used to test a condition, which can have True or False values. The simplest example of a block is:

if numberOfDogs < 2:
    print('Not enough dogs.')

We could also have an else statement:

if numberOfDogs < 2:
    print('Not enough dogs.')
else:
    print ('You probably have enough dogs.')

We can also add one or more elif (else if) statements:

if numberOfDogs < 2:
    print('Not enough dogs.')
elif numberOfDogs > 2:
    print ('Maybe you have too many dogs.')
else:
    print ('Just the right number of dogs.')

if statements can also be used to check if a value exists within an iterable such as a list, tuple, array, or string.

myPets=['cat','dog','fish','elephant','mouse']
if 'elephant' in myPets:
    print('Why did you get an elephant!')
str='We are in a python Course'
if 'We' in str:
    print (str)

for Statement

The for statement iterates over the items of a sequence (list, tuple, array, string, etc...), and performs the steps (executes the lines) within the for loop on each item.

MyList = ['salt', 'live turkey', 'candles']
for item in MyList:
    print (item,'live' in item,len(item))

Dictionaries can also be iterated through using items, keys, or values.

MyNight = {'Harder':'Better', 'Faster':'Stronger'}
for key in MyNight.keys():
    print(key)
for val in MyNight.values():
    print(val)
for key,val in MyNight.items():
    print(key,val)

while Statement

while is very similar to the if statement, but it does not repeat until the end of the loop. Instead, the while loop ends when a condition is met.

height = 0
while (height < 3):
    print ('You only jumped', height, 'meters. Jump Higher!')
    height = height + 1
print ("2 meters is as high as I got.")

break and continue

The break statement breaks out of the smallest enclosing for or while loop, ending the loop even if it has not finished. The continue statement continues with the next iteration of the same loop, skipping any commands of the loop after that point. Try and follow this example of a simple Blackjack game. Note that random.choice picks one random item (card) and random.shuffle will mix up the order of our list (deck):

import random
deck = list(range(1,12))
card1 = random.choice(deck)
score = card1
random.shuffle(deck)
for card in deck:
    score = score+card
    if score < 21:
        print("score is",score,"so give me another card.")
        continue
    if score == 21:
        print("Exactly 21, Blackjack!")
        break
    else:
        print("Must be over 21, Bust!")
        break

The game is different every time, so you can try running it until you win.

Here is a bit more complicated example where we look for our lost pets.

MissingPets  = {'dog':'Lennie','blobfish':'Frank'}
animals      = ['giraffe','dog','tarsier','blobfish','mouse']
names        = ['Stinky','Lennie','Frank']
for animal in animals:
    print('Is this your',animal)
    # Check you own the missing animal:
    if animal not in MissingPets.keys():
        print("No I don't have a",animal)
        # You don't own one, so you don't care what it's name is
        continue
    else:
        # You do own the animal, so check it's name:
        print("Yeah I have a",animal,"what's his name?")
        for name in names:
            print("Maybe his name is",name)
            if name == MissingPets[animal]:
                print("You found",name+'!')
                # Delete our found pet from the missing pets list
                del(MissingPets[animal])
                break
            else:
                print("No my",animal,"is not named",name)
    if len(MissingPets)==0:
        # No more missing pets, no need to keep looking.
        break

Now you can try to change the type and name of your missing pets, the script should find them every time.

range

As shown in previous chapters and examples, range is used to generate a list of numbers from start to end at an interval step. In Python 2, range generated a whole list object, whereas in Python 3, it is a special range generator object that does not use the memory redundantly.

print(range(4,25,4))
list(range(4,25,4))

Python Functions

Sections of a Python program can be put into an indented block (a container of code) defined as a function. A function can be called "on demand". A basic syntax is as follows:

def TheMultiplier(numba1,numba2):
    MyResult=numba2*numba1
    print("You have been multiplied:",MyResult)
    return
TheMultiplier(7,11)
type(TheMultiplier(3,7))
  • def identifies a function. The name of the function follows the def.

  • Parameters can be passed to a function. These parameter values are substituted before calculation.

  • return: Returns the result of the function. In the above example, because we didn't specify anything for the function to return, we get an empty NoneType object.

If the return command includes arguments, the result can be passed onto the statement that calls the function.

def TheMultiplier(numba1,numba2):
    MyResult=numba2*numba1
    return(MyResult)
thirteenXseven = TheMultiplier(13,7)
print(thirteenXseven)

Also, the default values of parameters can also be set. If the function is called without any arguments, the default values are used for calculation. Here is an example.

def TheMultiplier(numba1,numba2=3):
    MyResult=numba2*numba1
    return(MyResult)
TheMultiplier(2)
TheMultiplier(2,numba2=6)
TheMultiplier(2,7)

For details on defining function, refer here.

Python Modules

A module is a file containing Python definitions and statements. A module file (with .py ending) provides a module named filename. This module name is available once the module is imported.

def MultiplyBy7(x):
    return(x*7)
def MultiplyBy2(x):
    return(x*2)
def MultiplyByN(x,n):
    return(x*n)
def Always3():
    return(3)
  • After a file which includes a function is created and saved, the function can be used in an interactive shell within the directory (with the file) or in other files in the same directory as the module. If the saved filename is FirstModule.py, the function can be called in from another program file in the same directory.
import FirstModule as fm
print(fm.Always3())
print(fm.MultiplyBy2(7))

If the program is run, you can get the numbers 3 and 14.

Now add the following line to the end of FirstModule.py:

print("I've made a big mistake.")

and try to import the module in an interactive console.

import FirstModule as fm
↳ I've made a big mistake.

What you can see is that all of FirstModule.py was run when we imported it. So if you are mixing functions and executable code in the same ".py" file, you can run into problems. We can fix this issue by if the file is the main file, which is stored in the __name__ variable python automatically creates. So all code you don't want to run if the file is imported should be put in an if statement like this:

if __name__ == "__main__":
    print("I've avoided a big mistake.")

Now, if FirstModule.py is imported only the functions will run. But if FirstModule.py is run by itself, the code contained in if __name__ == "__main__": will still be executed.

Note that not only functions are imported, the variables defined in the module file can also be accessed as long as it is not within functions of the module. Try this by adding MyList=[1,3,7] to the end of FirstModule.py. Now MyList is accessable when we import FirstModule.

import FirstModule as fm
print (fm.MyList)

A list of all the objects from the module can be obtained by using dir() as

dir(fm)

Python Classes

As Python is a fully object-oriented language that provides class which allows you to create (instantiate) an object. A class is something that just contains structure – it defines how something should be laid out or structured (imagine a set of instructions), but doesn't actually fill in the content.

This is useful when a set of operations are to be carried out in several instances, and provides a distinction for every object created. Check out the following example.

from math import pi
class Circle:
    def __init__(self,radius):
        self.radius=radius
    def circumference(self):
        return(2*pi*self.radius)
    def area(self):
        return(pi*self.radius**2)

With the class Circle we can create circle objects which are of the same type and have the same fundamental properties:

circle1 = Circle(3)
circle2 = Circle(7)
type(circle1)
circle1.circumference()
circle2.circumference()
circle1.area()
circle2.area()
  • It is customary to name a class using upper case letters.

  • __init__ and self are critical to create an object.

  • self refers to the object itself

  • __init__ runs when the object is first called, so it is the function that creates the object self

which is general used to assign the attributes.

Now here is a bit more complicated example:

class Automobile:
    def __init__(self, nWheels, weight, color='red'):
        self.nWheels = nWheels
        self.color   = color
        self.weight  = weight
    def weightPerWheel(self):
        result = self.weight/self.nWheels
        return(result)
    def showColor(self):
        COLCODE = {
              'black'  : 40, # black
              'red'    : 41, # red
              'green'  : 42, # green
              'yellow' : 43, # yellow
              'blue'   : 44, # blue
              'violet' : 45, # violet
              'beige'  : 46, # beige
              'white'  : 47  # white
          }
        print('{1}'.format(COLCODE[self.color],self.color))

Let's play with our Automobile class.

car = Automobile(4,2100)
truck = Automobile(4,7000,color='white')
motorbike = Automobile(2,200,color='green')
truck.showColor()
car.showColor()
motorbike.weightPerWheel()
car.weightPerWheel()

Some simple and easy to understand examples of class are provided in:

Additional Relevant Modules

This section briefly introduces modules that are necessary while executing a Python program in the most efficient way.

sys Module

This module provides access to some variables used or maintained by the Python interpreter.

  • argv: Probably, the most useful of sys methods. sys.argv is a list object containing the arguments while running a python script from command lines. The first element is always the program name. Any number of arguments can be passed into the program as strings, e.g., sys.argv[1] is the second argument and so on.

  • byteorder: Remember the byteswap? sys.byteorder provides info on the machine Endianness.

  • path: The default path that Python searches is stored in sys.path. If you have written modules and classes, and want to access it from anywhere, you can add path to sys.path as,

sys.path.append('path to your directory')

A full set of sys methods is provided here.

os Module

This module provides a unified interface to a number of operating system functions. There are lots of useful functions for process management and file object creation in this module. Among them, it is especially useful to use functions for manipulating file and directory, which are briefly introduced below. For details on ‘OS module', click here.

Before using file and directory commands, it is necessary to import os,

import os
os.getcwd()

same as pwd in UNIX. Stands for present working directory and displays the absolute path to the current directory.

os.mkdir('dirname')

same as mkdir in UNIX. Makes a new directory. dirname can be absolute or relative path to the directory you want to create.

os.remove('filename')

same as rm in UNIX. Removes a file.

os.rmdir('dirname')

same as rm -r in UNIX. Removes a directory.

os.chdir('dirpath')

same as cd in UNIX. Change directory to the location shown by dirpath. dirpath can be absolute or relative.

os.listdir('dirpath')

same as ls in UNIX. Lists all files in a directory located at dirpath.

os.path.exists('filepath')

A very useful os function that checks if a file exists. Returns True if it exists and False if not.

If you want to know more about these functions, follow this.

Errors and Exceptions

There are two types of errors in Python, in general: Syntax Errors and Exceptions. Syntax error are caused by errors in Syntax. Exceptions may be caused by Value, Name, IO, Type, etc. A full list of exceptions in Python is here.

Python has builtin functions (try and except) to handle the exceptions. An example is below:

while True:
    try:
        x = int(rawinput("Please enter a number: "))
        break
    except ValueError:
        print ("Oops! That was no valid number. Try again...")

Tries to convert x to int. If a string is passed, it will raise ValueError and then goes to next iteration. The above is the simplest example, and there are many other more "sophisticated" ways to handle exceptions here.