2.4 Python Exceptions and Functions

Key Points

Introduction to Python exception handling

Introduction to Python functions

Preparation Before Class

Checking Pip Commands

Input pip in the command prompt or pip or pip3 in your terminal, and you will get how to use pip.

Course Content

Exception Handling

1. Python Built-in Exceptions

What is an exception?

  • An exception is an event, which occurs during the execution of a program that disrupts the normal flow of the program's instructions.
  • In general, when a Python script encounters a situation that it cannot cope with, it raises an exception.
  • An exception is a Python object that represents an error.
  • When a Python script raises an exception, it must either handle the exception immediately otherwise it terminates and quits.

Exception Name

Description

BaseException

Base class for all built-in exceptions

SystemExit

Raised when the sys.exit() function is called

KeyboardInterrupt

Raised when the user presses Ctrl+C, Ctrl+Z or Delete

Exception

Base class for all exceptions

StopIteration

Raised when the next() method of an iterator has no further values

GeneratorExit

Raised when a generator is closed (with the close() method)

StandardError

Base class for all built-in exceptions except StopIteration and SystemExit.

ArithmeticError

Raised when an error occurs in numeric calculations

FloatingPointError

Raised when a floating point calculation fails

OverflowError

Raised when the result of a numeric calculation is too large

ZeroDivisionError

Raised when the second operator in a division is zero

AssertionError

Raised when an assert statement fails

AttributeError

Raised when attribute reference or assignment fails

EOFError

Raised when the input() method hits an "end of file" condition (EOF)

EnvironmentError

Base class for all exceptions that occur outside the Python environment

IOError

Raised when an input or output operation fails

OSError

Raised when a system related operation causes an error

WindowsError

Raised when a Windows-specific error occurs

ImportError

Raised when an imported module does not exist

LookupError

Raised when errors raised cannot be found

IndexError

Raised when an index of a sequence does not exist

KeyError

Raised when a key does not exist in a dictionary

MemoryError

Raised when a program runs out of memory

NameError

Raised when a variable does not exist

UnboundLocalError

Raised when a local variable is referenced before assignment

ReferenceError

Raised when a weak reference object does not exist

RuntimeError

Raised when an error occurs that do not belong to any specific exceptions

NotImplementedError

Raised when an abstract method requires an inherited class to override the method

SyntaxError

Raised when a syntax error occurs

IndentationError

Raised when indentation is not correct

TabError

Raised when indentation consists of tabs or spaces

SystemError

Raised when a system error occurs

TypeError

Raised when two different types are combined

ValueError

Raised when there is a wrong value in a specified data type

UnicodeError

Raised when a unicode problem occurs

UnicodeDecodeError

Raised when a unicode decoding problem occurs

UnicodeEncodeError

Raised when a unicode encoding problem occurs

UnicodeTranslateError

Raised when a unicode translation problem occurs

Warning

Base class of all warning category classes

DeprecationWarning

Warnings about deprecated features when those warnings are intended for other Python developers

FutureWarning

Warnings about deprecated features when those warnings are intended for end users of applications that are written in Python

OverflowWarning

Raised when a calculation produces a result that is too large to be represented by the available memory or the data type being used

PendingDeprecationWarning

Warnings about features that will be deprecated in the future

RuntimeWarning

Warnings about dubious runtime features

SyntaxWarning

Warnings about dubious syntactic features

UserWarning

The default category for warn()

2. Detecting and Catching Python Exceptions

The try-except statement in Python is used to catch and handle exceptions.

It is used to test code for an error that is written in the try clause. If an error is encountered, the contents of the except clause are run. If you don't want to terminate your program when an exception occurs, just catch it in try.

Here is a simple syntax of try…except…else statement:

try:
You do your operations here;
......
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......
else:
If there is no exception then execute this block.

The working principle of try-except statement is:

  • When executing a try clause, Python marks the current program context so that it can return to this point when an exception occurs. Python will first execute the code in the try clause. What happens next depends on whether any exception occurs during execution.
  • If an exception occurs in the try clause, Python jumps to the except clause and executes the corresponding code that matches the exception. Once the exception is handled, the control flow passes through the entire try clause (unless a new exception is raised when handling the exception).
  • If no matching except clause is found, the exception is propagated to the upper-level try clause or to the top level of the program (which will terminate the program and print out the default error message).
  • If no exception is raised in the try clause, the else clause will be executed (if there is an else clause). Then the control flow passes through the entire try clause.

This example opens a file, writes content in the file, and comes out successfully because there is no problem at all:

#!/usr/bin/python

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print "Error: can\'t find file or read data"
else:
   print "Written content in the file successfully"
   fh.close()

This produces the following result:

Written content in the file successfully

This example tries to open a file where you do not have write permission, so it raises an exception:

#!/usr/bin/python

try:
   fh = open("testfile", "r")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print "Error: can\'t find file or read data"
else:
   print "Written content in the file successfully"

This produces the following result:

Error: can't find file or read data

Python Functions

1. Definition of Functions

You can define functions to provide the required functionality. Here are simple rules to define a function in Python:

  • Function blocks begin with the keyword def followed by the function name and parentheses ().
  • Any input parameters or arguments should be placed within these parentheses. You can also define parameters inside these parentheses.
  • The first statement of a function can be an optional statement the documentation string of the function or docstring.
  • The code block within every function starts with a colon (:) and is indented.
  • The statement return [expression] exits a function, optionally passing back an expression to the caller. A return statement with no arguments is the same as return None.

Defining a Function

In Python, a function is defined using the def keyword.

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x
print(my_abs(-99))

Can a function return multiple values?

import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny
x, y = move(100, 100, 60, math.pi / 6)
print(x, y)

Parameters and Arguments

  • A parameter is the variable listed inside the parentheses in the function definition.
  • An argument is the value that is sent to the function when it is called.

In the following example, the userName is the parameter, while David is the argument.

Local Variables and Global Variables

  • Local variables are those which are defined inside a function and their scope is limited to that function only.
  • Global variables are those which are not defined inside any function and have a global scope.
#!/usr/bin/python
total = 0 #a global variable
#define a function
def sum(arg1, arg2):
   #return the sum of the two arguments
   total = arg1 + arg2 #total is a local variable
   print ("a local variable : ", total)
   return total
#call the sum function
sum( 10, 20 )
print("a global variable : ", total)

Declare a variable as a global variable in a function:

#Define a global variable in a function
a=0
def plus_a():
  global a
  a +=1

Arguments

1. Positional Arguments

Write a function to calculate x2:

def power(x):
    return x * x

In the power(x) function, x is a positional argument. When you call the power() function, you must pass in one and only one positional argument x.

>>> power(5)
25
>>> power(15)
225

Note that the power() function only calculates the square of a number. Then how to calculate the cube of a number or any higher power?

You can modify the function definition to accept an exponent as a second argument. Then the function changes into power(x, n).

def power(x, n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

This function calculates the result of raising a given number x to the power of a given exponent n.

>>> power(5, 2)
25
>>> power(5, 3)
125

In the power(x, n) function, x and n are both positional arguments. When you call the power() function, the arguments are passed to the function in the order they are listed in the function definition.

2. Default Arguments

After defining the power(x, n) function, you cannot call the power(x) function successfully. This is because the new function has the same name as the old function and then replaces it. Therefore, when you try to call the old power(x) function, Python will show that the function lacks an argument.

>>> power(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: power() missing 1 required positional argument: 'n'

The TypeError shows that the power() function is missing one required positional argument n. In this case, you can use default arguments to call the power(x) function.

Modify the power(x, n) function to use a default value of 2 for the n parameter:

def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

In this way, when you call power(5), it's equivalent to calling power(5, 2):

>>> power(5)
25
>>> power(5, 2)
25

If you want to call the power(x, n) function with a value of n other than the default value of 2, you can pass the value as the second argument, such as power(5, 3).

Here are some tips for setting default arguments:

  • Mandatory parameters come before default parameters, otherwise, the Python interpreter will raise an error.
  • It is important to know how to set default arguments.

When a function has multiple parameters, it is recommended to place the parameters that are subject to frequent changes before the ones that remain mostly constant. The parameters that remain constant can be set as default parameters. Therefore, default arguments make the function easier to call.

3. Variable-length Arguments

Variable-length arguments are a way to pass an arbitrary number of arguments to a function. For example, the number of arguments can be one, two, or zero. There are two types of variable-length arguments, non-keyword variable-length arguments and keyword variable-length arguments.

1) Non-keyword Arguments

Suppose there is a list of a, b, c... and you want to calculate a2+b2+c2+... in Python.

To define this function, you need to determine the input parameters. Since the number of parameters is uncertain, you may want to pass a, b, c... as a list or tuple. The function can be defined as follows:

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

You must first create a list or tuple before calling the function:

>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84

However, you can also use variable-length arguments:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

Variable-length arguments allow you to pass an arbitrary number of arguments directly to the function without the need for a list or tuple. You only need to add an asterisk (*) before the parameter name. Inside the function, the arguments are automatically packed into a tuple, so the function code remains unchanged. When calling the function, any number of arguments can be passed, including zero.

>>> calc(1, 2)
5
>>> calc()
0

If you already created a list or tuple, how to call a function with variable-length arguments? Input:

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14

This method is too complicated. You can also use the * operator to unpack the elements and pass them as separate arguments to the function.

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

Note: nums means passing all the elements of the nums list as variable-length arguments. This writing method is very useful and common.

2) Keyword Arguments

The above example shows that non-keyword variable-length arguments allow you to pass in any number of arguments to a function, and these arguments are automatically packed into a tuple when the function is called.

Keyword variable-length arguments, on the other hand, allow you to pass in any number of keyword arguments to a function. The arguments are automatically packed into a dictionary, and the parameter with two asterisks (**) before all the keyword arguments. For example:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

The function person takes three arguments. The first two arguments, name and age, are mandatory, while the third argument **kw is optional. When you call this function, you can just pass in the mandatory parameters.

>>> person('Michael', 30)
name: Michael age: 30 other: {}
#You can pass any number of arguments to the function
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

Then what is the use of keyword arguments? It can extend the functionality of the function.

For example, in the person function, you can not only receive the name and age parameters but also other parameters if the caller wants to provide more information.

Imagine you are designing a user registration program, you want to set the username and age as required fields and all other fields as optional. Then using keyword variable-length arguments to define a function can meet your needs.

Similar to non-keyword arguments, you can use a dictionary to pass keyword arguments to a function:

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

Of course, the above complex call can be simplified as follows:

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

Extra means to pass all the key-value pairs of the variable as keyword arguments to the kw parameter of the function. The kw parameter will receive a dictionary, which is a copy of the dictionary extra. Note that changes to kw will not affect extra outside the function.

Was this information helpful?
Yes
NoNo
Need more help? Contact support