Exceptions in Python

These are my notes on exceptions in python.

Ankr Store on Amazon, keep your electronics charged by the best! If you buy something, I get a small commission and that makes it easier to keep on writing. Thank you in advance if you buy something.

Exceptions
Sections of a python script in which it is possible to anticipate errors, such
as those handling user input, can be enclosed in a "try except" block to handle
exception errors. The statements to be executed are grouped in a try : block,
and exceptions are passed to the ensuing except : block for handling.
Optionally, this may be followed by a finally : block containing statements to
be executed after exceptions have been handled.

Python recognizes many built in exceptions such as the nameError, which occurs
when a variable name is not found, the indexError, which occurs when trying to
address a non-existent list index, and the ValueError, which occurs when a
built-in operation or function receives an argument that has an inappropriate
value.

Each exception returns a descriptive message that can be assigned to a variable
with the "as" keyword. This can be used to display the nature of the exception
when it occurs.

title='Princeton Companion To Mathematics'

try:
    print(titel)

except NameError as msg:
    print(msg)

Run that and you can see how the error will get handled.

Multiple exceptions can be handled by specifying their type as a comma-separated
list in parentheses within the except block.

You can also make the interpreter report an exception by using the raise keyword
to specify the type of exception to be recognized and a custom descriptive
message in parentheses.

day=32
try:
    if day > 31 :
        raise ValueError('invalid day number')

except ValueError as msg:
    print('the program found AN', msg)

finally :
    print('but today is beautiful anyway')

Statements in the try block are all executed unless or until an exception
occurs.

Assertions
When tracking down errors in your code it is often useful to comment out one or
more lines of code by prefixing each line with the hash character. The Python
interpreter will then omit execution of those lines to help localize where a
problem lies. 

Another useful debugging technique employs the Python assert keyword to add
error-checking code to your script. This examines a specified test expression
for a boolean True or False result, and reports an AssertionError when the test
fails. Optionally, an assert statement can include a descriptive message to
supply when reporting an AssertionError.

When the test expression fails, the interpreter reports the AssertionError and
halts execution of the script, but when the test succeeds, the assert statement
does nothing, and execution of the script continues.

Employing assert statements is an effective way to document your script, as
their descriptive messages provide commentary and their tests alert you when
your code is erroneous.

Assert versus Exception
At first glance, an AssertionError can appear confusingly similar to an
exception, but it is important to recognize their distinctions:
1. Expections provide a way to handle errors that may legitimately occur at
   runtime.
2. AssertionErrors provide a way to alert the programmer to mistakes during
   development.

Typically, assert statements will be removed from release versions of a program
after debugging is complete, whereas except statements will remain to handle
runtime errors. You can have the interpreter ig nore all assert statements using
a -o switch in the run command, for example, python -O assert.py

chars=['alpha', 'beta', 'gamma', 'delta', 'epsilon']

def display(elem):
    assert type(elem) is int, 'argument must be integer'
    print('list element', elem, '=', chars[elem])

elem=4
display(elem)

elem=elem/2
display(elem)

This AssertionError occurs because the division operation returns a float value,
not an integer value.

Functions are defined using the def keyword, and contain indented statements to
execute when the function gets called.
Variables with global scope can be referenced from anywhere, but variables with
local scope can only be referenced from within the function in which they are
declared.
Arguments are declared as a comma-separated list within the parentheses of a
function definition.
Function calls must supply data for each function argument unless a default
value is specified in their declarations.
Optionally, a function can include a return statement to return a value to the
caller.
An anonymous function containing a single expression is created with the lambda
keytword, and returns a function object. 
Callbacks are frequently coded as inline lambda expressions embeded directly in
a caller's argument list.

Placeholders can be created by inserting the pass keyword where a statement is
required syntactically.
A generator function is created when a statement using the yield keyword appears
in its function block.
Generator functions retain the state of the function when last called, and
return a generator object to the caller.
The built in next() function can be used to continue execution of a generator
function from the point where it was frozen.
Anticipated runtime exception errors can be handled by enclosing statements in a
try except block.
Optionally, a finally statement can be used to specify statements to be executed
after exceptions have been handled.
Error-checking code can be added to scripts using the assert keyword to report
development errors.