introduction to computing using python perkovic, chapter 7 functions revisited python namespaces...
TRANSCRIPT
Introduction to Computing Using Python
Perkovic, Chapter 7
Functions revisitedPython NamespacesPython error-handling
Introduction to Computing Using Python
Why write code as functions?
1. Modularity2. Code reuse3. Encapsulation: A function hides its
implementation details from a “client” (the user of the function)
Introduction to Computing Using Python
Encapsulation through local variables
def double(y): x=2 print('x = {}, y = {}'.format(x,y)) return x*y
• x and y are local variables• x and y exist only during the execution of
a function call to double
Encapsulation makes modularity and code reuse possible
Introduction to Computing Using Python
Namespaces and modules
A namespace is a mapping from names to objects
Several different kinds of namespaces:
• Global: associated with idle window• Local: associated with a function• Module: associated with a .py file that is
imported into another namespace
Introduction to Computing Using Python
Local namespaces
When a function is called, a new namespace is created. The namespace only exists for as long a the function is executing
Variables defined within the function (local variables) exist within the function’s namespace
It is not possible to access a local variable from another namespace
Local variable names shadow any names within the global namespace, so that the global names are not accessible
Introduction to Computing Using Python
Local namespace example>>> a=0>>>def multiply(a,b):
return a * b>>> a0>>> multiply(2,3) # temporarily creates a new namespace6>>> a0>>> bTraceback (most recent call last): File "<pyshell#0>", line 1, in <module> bNameError: name 'b' is not defined
Introduction to Computing Using Python
Global namespace
The idle window is associated with a global namespace
Variables, functions, etc. that are defined in the idle window are in the global namespace
Unlike local namespaces, the global namespace exists for as long as an idle window is open (although the namespace is cleared when you hit F5)
Names that are in the global namespace are accessible form a local namespace, unless the name is shadowed
Introduction to Computing Using Python
Global namespace example
>>> a = 2>>> def multiplyByA(b):
return a * b>>> multiplyByA(3)6>>> def changeA(value):
a = value # this is still the global a>>> changeA(5)>>> a 2
Introduction to Computing Using Python
Module namespace
A module is Python code that is written in a .py file
The names in a module must be imported in order to use them
There are 3 different kinds of import statements:
import <module> from <module> import <name>from <module> import *
Introduction to Computing Using Python
Module namespace, cont.
import <module>
names in module are brought into the global namespace, but must be referred to as <module>.<name>
>>> import math>>> math.sqrt(2)1.4142135623730951>>> sqrt(2)Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> math.min(1,2)AttributeError: 'module' object has no attribute ‘sqrt'
Introduction to Computing Using Python
Module namespace, cont.
from <module> import <name>
A name in the specified module are brought into the global namespace, and can be referred to by its name
>>> from math import sqrt>>> sqrt(2)1.4142135623730951
Introduction to Computing Using Python
Module namespace, cont.
from <module> import *
All name in the specified module are brought into the global namespace, and can be referred to by its name
>>> from math import *>>> min(1,2,3)1
BUT, any previously defined names can no longer be referred to
Introduction to Computing Using Python
Module namespace, cont.
>>> sqrt = 5>>> from math import *>>> min(1,2,3)1>>> sqrt<built-in function sqrt>
This might not be what you want
Introduction to Computing Using Python
Module and names
Importing a module using import <module> allows you to keep more than one meaning of a name
This helps with programming modularity (hence the name module)
If a large prorgramming project is broken up among several programmers, each can write a module with no concern about the names that other programmers use in their modules
Introduction to Computing Using Python
Local vs. global variables
A local variable one that is used within a function
>>> a = 1>>> def f(a,b):
a = a * breturn a
>>> f(2,2)4>>> a1
Introduction to Computing Using Python
Local vs. global variables
>>> a = 1>>> def f(c,d):
a = c * dreturn a
>>> f(2,2)4>>> a1
Introduction to Computing Using Python
Using a global variable in a function
>>> a = 1>>> def f(c,d):
global aa = c * dreturn a
>>> f(2,2)4>>> a4
Introduction to Computing Using Python
Subtle distinctions between local and global variables
>>> a = 2>>> def f(b):
return b * a>>> f(3)6>>> a2
Introduction to Computing Using Python
Subtle distinctions between local and global variables>>> a = 2>>> def f(b):
a = a * breturn a
>>> f(3)Traceback (most recent call last): File "<pyshell#52>", line 1, in <module> f(3) File "<pyshell#51>", line 2, in f a = a * bUnboundLocalError: local variable 'a' referenced before assignment
Introduction to Computing Using Python
How Python evaluates names
When the Python interpreter needs to evaluate a name, it searches for the name definition in this order:
1. the enclosing function call namespace2. the global (module) namespace3. the namespace of module builtins
Introduction to Computing Using Python
Exceptions, revisitedWhen program execution gets into an erroneous state, an exception object is created
• This object has a type that is related to the type of error• The object contains information about the error• The default behavior is to print this information and
interrupt the execution of the statement that “caused” the error
Introduction to Computing Using Python
Exceptional control flow
>>> f(2)>>> f(2)Start f>>> f(2)Start fStart g
>>> f(2)Start fStart gStart h
n = 2
f(2)
n = 1
g(1)
n = 0
h(0)
n = 2print('Start f')
f(2)
n = 2print('Start f')g(n-1)
f(2)
n = 2print('Start f')g(n-1)
print(n)
f(2)
n = 1print('Start g')
g(1)
n = 1print('Start g')h(n-1)
g(1)
n = 1print('Start g')h(n-1)
print(n)g(1)
n = 0print('Start h')print(1/n)
h(0)
n = 0print('Start h')
h(0)
n = 0print('Start h')print(1/n)print(n)
h(0)
>>> f(2)Start fStart gStart hTraceback (most recent call last): File "<pyshell#79>", line 1, in <module> f(2) File "/Users/me/ch7/stack.py", line 13, in f g(n-1) File "/Users/me/ch7/stack.py", line 8, in g h(n-1) File "/Users/me/ch7/stack.py", line 3, in h print(1/n)ZeroDivisionError: division by zero>>>
Normal control flowExceptional control flow
The default behavior is to interrupt the execution of each “active” statement and print the error information contained in the exception object.
1. def h(n):2. print('Start h')3. print(1/n)4. print(n)5. 6. def g(n):7. print('Start g')8. h(n-1)9. print(n )10. 11. def f(n):12. print('Start f')13. g(n-1)14. print(n)
Introduction to Computing Using Python
Catching and handling exceptions
It is possible to override the default behavior (print error information and “crash”) when an exception is raised, using try/except statements
strAge = input('Enter your age: ')intAge = int(strAge)print('You are {} years old.'.format(intAge))
try: strAge = input('Enter your age: ') intAge = int(strAge) print('You are {} years old.'.format(intAge))except: print('Enter your age using digits 0-9!')
>>> ======================== RESTART ========================>>> Enter your age: fifteenTraceback (most recent call last): File "/Users/me/age1.py", line 2, in <module> intAge = int(strAge)ValueError: invalid literal for int() with base 10: 'fifteen'>>>
>>> ========== RESTART ==========>>> Enter your age: fifteenEnter your age using digits 0-9!>>>
Default behavior:Custom behavior:
If an exception is raised while executing the try block, then the block of the associated except statement is executed
Introduction to Computing Using Python
Format of a try/except statement pair
try: <indented code block>except: <exception handler block><non-indented statement>
The format of a try/except pair of statements is:
The exception handler handles any exception raised in the try block
The except statement is said to catch the (raised) exception
It is possible to restrict the except statement to catch exceptions ofa specific type only
try: <indented code block>except <ExceptionType>: <exception handler block><non-indented statement>
>>> readAge('age.txt')Value cannot be converted to integer.>>>
Introduction to Computing Using Python
Format of a try/except statement pair
It is possible to restrict the except statement to catch exceptions ofa specific type only
def readAge(filename): 'converts first line of file filename to an integer and prints it' try: infile = open(filename) strAge = infile.readline() age = int(strAge) print('age is', age)except ValueError: print('Value cannot be converted to integer.')
1 fifteen
age.txt
>>> readAge('age.txt')Value cannot be converted to integer.>>> readAge('age.text')Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> readAge('age.text') File "/Users/me/ch7.py", line 12, in readAge infile = open(filename)IOError: [Errno 2] No such file or directory: 'age.text'>>>
default exception handler prints this
Introduction to Computing Using Python
Multiple exception handlers
It is possible to restrict the except statement to catch exceptions ofa specific type only
def readAge(filename): 'converts first line of file filename to an integer and prints it' try: infile = open(filename) strAge = infile.readline() age = int(strAge) print('age is',age) except IOError: # executed only if an IOError exception is raised print('Input/Output error.') except ValueError: # executed only if a ValueError exception is raised print('Value cannot be converted to integer.') except: # executed if an exception other than IOError or ValueError is raised print('Other error.')
Introduction to Computing Using Python
Controlling the exceptional control flow
>>> try: f(2)except: print('!!')
>>> try: f(2)except: print('!!')
Start f
>>> try: f(2)except: print('!!')
Start fStart g
>>> try: f(2)except: print('!!')
Start fStart gStart h
n = 2
f(2)
n = 1
g(1)
n = 0
h(0)
n = 2print('Start f')
f(2)
n = 2print('Start f')g(n-1)
f(2)
n = 2print('Start f')g(n-1)
print(n)
f(2)
n = 1print('Start g')
g(1)
n = 1print('Start g')h(n-1)
g(1)
n = 1print('Start g')h(n-1)
print(n)g(1)
n = 0print('Start h')print(1/n)
h(0)
n = 0print('Start h')
h(0)
n = 0print('Start h')print(1/n)print(n)
h(0)
1. def h(n):2. print('Start h')3. print(1/n)4. print(n)5. 6. def g(n):7. print('Start g')8. h(n-1)9. print(n )10. 11. def f(n):12. print('Start f')13. g(n-1)14. print(n)
>>> try: f(2)except: print('!!')
Start fStart gStart h!!
>>> import math>>>>>> import math>>> dir(math)['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc’]>>>
>>> import math>>> dir(math)['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc’]>>> math.sqrt<built-in function sqrt>>>> math.pi3.141592653589793
Introduction to Computing Using Python
Modules
When the module is executed (imported), then the module is (also) a namespace.
A module is a file containing Python code.
When the module is executed (imported), then the module is (also) a namespace.
• This namespace has a name, typically the name of the module.
When the module is executed (imported), then the module is (also) a namespace.
• This namespace has a name, typically the name of the module.• In this namespace live the names that are defined in the global scope of the
module: the names of functions, values, and classes defined in the module. • These names are the module’s attributes.
When the module is executed (imported), then the module is (also) a namespace.
• This namespace has a name, typically the name of the module.• In this namespace live the names that are defined in the global scope of the
module: the names of functions, values, and classes defined in the module.
Built-in function dir() returns the names defined in a namespace
To access the imported module’s attributes, the name of the namespace must be specified
Introduction to Computing Using Python
Importing a module
When the Python interpreter executes an import statement, it:1. Looks for the file corresponding to the module to be imported.2. Runs the module’s code to create the objects defined in the module.3. Creates a namespace where the names of these objects will live.
An import statement only lists a name, the name of the module• without any directory information or .py suffix.
Python uses the Python search path to locate the module.• The search path is a list of directories where Python looks for modules.• The variable name path defined in the Standard Library module sys refers
to this list.
When the Python interpreter executes an import statement, it:1. Looks for the file corresponding to the module to be imported.
>>> import sys>>> sys.path['/Users/me', '/Library/Frameworks/Python.framework/Versions/3.2/lib/python32.zip', . . .'/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages']>>>
current working directory Standard Library folders
>>> ================ RESTART ================>>> dir()['__builtins__', '__doc__', '__name__', '__package__']>>> import exampleTraceback (most recent call last): File "<pyshell#79>", line 1, in <module> import exampleImportError: No module named example>>>
>>> ================ RESTART ================>>> dir()['__builtins__', '__doc__', '__name__', '__package__']>>>
Introduction to Computing Using Python
The Python search path
Suppose we want to import module example stored in folder /Users/me that is not in list sys.path
>>> ================ RESTART ================>>>>>> ================ RESTART ================>>> dir()['__builtins__', '__doc__', '__name__', '__package__']>>> import exampleTraceback (most recent call last): File "<pyshell#79>", line 1, in <module> import exampleImportError: No module named example>>> import sys>>> sys.path.append('/Users/me')>>> import example>>> example.f<function f at 0x10278dc88>>>> example.x0>>>
>>> ================ RESTART ================>>> dir()['__builtins__', '__doc__', '__name__', '__package__']>>> import exampleTraceback (most recent call last): File "<pyshell#79>", line 1, in <module> import exampleImportError: No module named example>>> import sys>>> sys.path.append('/Users/me')>>> import example>>> example.f<function f at 0x10278dc88>>>> example.x0>>> dir()['__builtins__', '__doc__', '__name__', '__package__', 'example', 'sys’]
By just adding folder /Users/me to the search path, module example can be imported
When called without an argument, function dir() returns the names in the top-level module
• the shell, in this case.
'an example module'def f(): 'function f' print('Executing f()')
def g(): 'function g' print('Executing g()') x = 0 # global var
names in the shell namespace; note that example is not inno folder in the Python search path contains module example
Introduction to Computing Using Python
Three ways to import module attributes
'an example module'def f(): 'function f' print('Executing f()')
def g(): 'function g' print('Executing g()') x = 0 # global var
example.txt
namespace __main__
>>>
f
module example
example
f() 0
g x
g()
1. Import the (name of the) module
>>> import example>>>>>> import example>>> example.x0>>> example.f<function f at 0x10278dd98>>>> example.f()Executing f()>>>
Introduction to Computing Using Python
Three ways to import module attributes
'an example module'def f(): 'function f' print('Executing f()')
def g(): 'function g' print('Executing g()') x = 0 # global var
example.txt
namespace __main__
>>>
f
module example
f
f() 0
g x
g()
2. Import specific module attributes
>>> from example import f>>> >>> from example import f>>> f()Executing f()>>> xTraceback (most recent call last): File "<pyshell#28>", line 1, in <module> xNameError: name 'x' is not defined>>>
Introduction to Computing Using Python
Three ways to import module attributes
'an example module'def f(): 'function f' print('Executing f()')
def g(): 'function g' print('Executing g()') x = 0 # global var
example.txt
namespace __main__
>>>
3. Import all module attributes
>>> from example import *>>> >>> from example import *>>> f()Executing f()>>> g()Executing g()>>> x0>>>
f
module example
f
f() 0
g x
g()
g x