introduction to computing using python perkovic, chapter 7 functions revisited python namespaces...

33
Introduction to Computing Using Py Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

Upload: eddie-mccullough

Post on 02-Apr-2015

276 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

Introduction to Computing Using Python

Perkovic, Chapter 7

Functions revisitedPython NamespacesPython error-handling

Page 2: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python 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)

Page 3: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 4: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 5: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 6: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 7: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 8: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 9: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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 *

Page 10: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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'

Page 11: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 12: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 13: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 14: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 15: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 16: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

Introduction to Computing Using Python

Local vs. global variables

>>> a = 1>>> def f(c,d):

a = c * dreturn a

>>> f(2,2)4>>> a1

Page 17: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 18: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

Introduction to Computing Using Python

Subtle distinctions between local and global variables

>>> a = 2>>> def f(b):

return b * a>>> f(3)6>>> a2

Page 19: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 20: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 21: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 22: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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)

Page 23: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 24: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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>

Page 25: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

>>> 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

Page 26: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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.')

Page 27: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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!!

Page 28: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

>>> 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

Page 29: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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

Page 30: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

>>> ================ 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

Page 31: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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()>>>

Page 32: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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>>>

Page 33: Introduction to Computing Using Python Perkovic, Chapter 7 Functions revisited Python Namespaces Python error-handling

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