• Python provide 2 ways to handle unexpected
error: exception and assert.
• Exception handling: is an event, which occurs
during the execution of a program, that disrupts
the normal flow of the program's instructions.
• The exceptions are defined in the built-in class
• For example: If divided by 0, we want to raise an
• It is defined on the warnings module
• The raise statement allows the programmer
to force a specified exception to occur
• Raise statement is to raise an exceptions, tryexception-finally clause is to catch an
exceptions and decide how to do.
Try …except…finally structure
First, the try clause(print 100/0) is executed
If no exception occurs, the except clause is skipped
Otherwise, the rest of the try clause is skipped. Go to the line its type
matches the exception name(ZeroDivisionError).
Clean-up info in the finally sentence. It executed under all conditions
Write User-defined Exceptions
>>> class MyError(Exception):
... def __init__(self, value):
self.value = value
... def __str__(self):
• Define user-defined exception MyError.
• Raise an exception when x == 0. Also write the try-except-finally
• When call f(0,100), the exception is raised and catched.
Brief introduction of assert
• The assert clause is used on situation or
condition that should never happen. For
example: assert 1>0
• “assert” statement is removed when the
compilation is optimized (-O and -OO option,
it is because __debug__ change to False
when -O or -OO option are added).
• So It is a convenient way to insert debugging
assertion into a program
• We can see assert is ignored when add -O
• Generator s are a simple and powerful tool for
• Use yield statement instead of return to return
• the __iter__() and next() methods are created
automatically. The local and execution state are
• When generator terminate, it raise StopIteration
• When you call the generator function, the co
de does not run. It just return the generator
The difference between generator
and sequence type
>>> mylist = [x*x for x in range(3)]
>>> mygenerator = (x*x for x in range(3))
•Both mylist and mygenerator are iterable
•But you can only read
•Generator do not store all
the values in memory, they
generate the values on the
• Functions are objects in python.
• We can define other function inside function
• We can pass a function as argument of other
benchmark function accept
func as input argument.
• We can see @benchmark
apply benchmark function
f = benchmark(f)
This is the typical usage of
decorator: Use func as input
argument. define wrapper
function inside function
• PEP - 318 Decorators for Functions and
• A descriptor is an object attribute with
• If any of __get__(), __set__() and
__delete__() are defined for an object, it is
said to be a descriptor.
• If an object defines both __get__() and __set__(), it is considered
a data descriptor.
• Descriptors that only define __get__() are called non-data
• descriptors are invoked by the __getattribute__() method
• overriding __getattribute__() prevents automatic descriptor
• Define __set__ and __get__ method.
Implement the property() method
• Calling property() is a succinct way of building
a data descriptor
Let us write the similar property()
Function are non-data descriptor
• All functions include __get__() method for
Non-data descriptor staticmethod
• The pure python verson of static method
should be like:
Use static method
Non-data descriptor classmethod
• Pure python version of classmethod looks