week5
week5
Week5
Decomposition, Abstraction and
Functions
Reading:
▪ Chapter 4 of Guttag’s Book
2
Programming Exercise
• Write a script that finds the first 100 positive even integers, computes and
displays their sum.
3
Programming Exercise
• You have three identical prizes to give away and a pool of 30 finalists.
• The finalists are assigned numbers from 1 to 30.
• Write a program to randomly select the numbers of three finalists to
receive a prize.
• Make sure not to pick the same number twice.
• For example, picking finalists 3, 15, 29 would be valid but picking 3, 3, 31
would be invalid because finalist number 3 is listed twice and 31 is not a
valid finalist number.
4
Programming Exercise
• Write a script that displays the following triangle pattern
• Use for loops to generate the patterns. Display all asterisks (*) with a
single statement of the form print('*', end=‘’) which causes the
asterisks to display side by side.
5
Programming Exercise
• Write a script that displays the following triangle pattern
• Use for loops to generate the patterns. Display all asterisks (*) with a
single statement of the form print('*', end=‘’) which causes the
asterisks to display side by side.
6
Homework
• Write a script that displays the following triangle pattern
• Use for loops to generate the patterns. Display all asterisks (*) with a
single statement of the form print('*', end=‘’) which causes the
asterisks to display side by side.
7
How Do We Write Code?
• So far:
8
Find Approximation to Square Root of x
if x < 0:
print('Does not exist')
else:
low = 0
high = max(1, x)
ans = (high + low)/2
while abs(ans**2 - x) >= epsilon:
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2
print(ans, 'is close to square root of', x)
9
How Do We Write Code?
• Code lacks general utility:
• Want to reuse it? → Need to copy the code, possibly edit the variable
names, and paste it where we want it
• Cannot easily use this computation inside of some other, more complex,
computation
• Want to compute cube roots rather than square roots? → Have to edit the
code
10
Summing a Square Root and a Cube root
• Show code in Spyder
• The more code a program contains, the more chance something can go
wrong, and the harder the code is to maintain.
11
How Do We Write Code?
• Problems with this approach:
• How do you know the right info is supplied to the right part of code
12
Good Programming
• More code not necessarily a good thing
• Introduce functions
13
Example – Projector
• A projector is a black box
• don’t know how it works
• know the interface: input/output
• connect any electronic to it that can communicate with that input
• black box somehow converts image from input source to a wall,
magnifying it
14
Example – Projector
• projecting large image for Olympics decomposed into separate tasks for
separate projectors
15
Let's Apply These
Concepts
TO PROGRAMMING!
16
Create Structure With Decomposition
• in projector example, separate devices
• in programming, divide code into modules
▪ are self-contained
▪ used to break up code
▪ intended to be reusable
▪ keep code organized
▪ keep code coherent
17
Suppress Details With Abstraction
• in projector example, instructions for how to use it are sufficient, no need
to know how to build one
• in programming, think of a piece of code as a black box
▪ cannot see details
▪ do not need to see details
▪ do not want to see details
▪ hide tedious coding details
18
Functions
• Write reusable pieces/chunks of code, called functions
• functions are not run in a program until they are “called” or “invoked” in a
program
• function characteristics:
▪ has a name
▪ has parameters (0 or more)
▪ has a docstring (optional but recommended)
▪ has a body
▪ returns something
19
Function Definitions
• In Python each function definition is of the form
20
Function Definitions
• In Python each function definition is of the form
21
Function Definitions
• In Python each function definition is of the form
22
Function Definitions
• In Python each function definition is of the form
23
Function Definitions
• The formal parameters are bound (as in an assignment statement) to the
actual parameters (also called arguments) of the function invocation
(also referred to as a function call).
24
Function Definitions
• The value of the expression max_val(3,4)*max_val(3,2) is 12,
because the first invocation of max_val returns the int 4 and the
second returns the int 3
25
The return statement
• Execution of a return statement terminates an invocation of the function
26
Function Definitions
27
Function Definitions
28
Function Invocation
• When a function is called, sequence of events:
1. The expressions that make up the actual parameters are evaluated, and
the formal parameters of the function are bound to the resulting values.
▪ max_val(3+4, z) will bind the formal parameter x to 7 and the formal
parameter y to whatever value the variable z has
29
Function Invocation
3. The code in the body of the function is executed until either
▪ a return statement is encountered and the value of the expression following
the return becomes the value of the function invocation
▪ there are no more statements to execute, and the function returns None
30
Lambda Abstraction
• Parameters allow programmers to write code that accesses not specific
objects, but instead whatever objects the caller of the function chooses to
use as actual parameters
31
A Function for Finding Roots
def find_root(x, power, epsilon):
if x < 0 and power%2 == 0:
return None #Negative number has no even-powered roots
low = min(-1, x)
high = max(1, x)
ans = (high + low)/2
while abs(ans**power - x) >= epsilon:
if ans**power < x:
low = ans
else:
high = ans
ans = (high + low)/2
32
return ans
Test Functions
• Pay big dividends
• Beat sitting at a keyboard and typing test cases into the shell over and
over during debugging the process of finding out why a program does not
work, and then fixing it
33
A Test Function for Finding Roots
def test_find_root(x_vals, powers, epsilons):
for x in x_vals:
for p in powers:
for e in epsilons:
result = find_root(x, p, e)
if result == None:
val = 'No root exists'
else:
val = 'Okay'
if abs(result**p - x) > e:
val = 'Bad'
print(f'x = {x}, power = {p}, epsilon = {e}: {val}')
34
A Test Function for Finding Roots
x_vals = (0.25, 8, -8)
powers = (1, 2, 3)
epsilons = (0.1, 0.001, 1)
test_find_root(x_vals, powers, epsilons)
• Three tuples (i.e., sequences of values) of length three, one call checks 27
combinations of parameters.
35
Keyword Arguments and Default Values
• Two ways that formal parameters get bound to actual parameters:
36
Keyword Arguments and Default Values
def print_name(first_name, last_name, reverse):
if reverse:
print(last_name + ', ' + first_name)
else:
print(first_name, last_name)
37
Keyword Arguments and Default Values
• Each of the following is an equivalent invocation of print_name:
38
Keyword Arguments and Default Values
• Though the keyword arguments can appear in any order in the list of
actual parameters, it is not legal to follow a keyword argument with a non-
keyword argument.
39
Keyword Arguments and Default Values
• Keyword arguments are commonly used in conjunction with default
parameter values.
40
Keyword Arguments and Default Values
• Default values allow programmers to call a function with fewer than the
specified number of arguments.
print_name('Olga', 'Puchmajerova')
print_name('Olga', 'Puchmajerova', True)
print_name('Olga', 'Puchmajerova', reverse = True)
will print
Olga Puchmajerova
Puchmajerova, Olga
Puchmajerova, Olga
41
Keyword Arguments and Default Values
• Using keyword arguments reduces the risk of unintentionally binding an
actual parameter to the wrong formal parameter.
• The line of code leaves no ambiguity about the intent of the programmer
who wrote it.
42
Variable Number of Arguments
• Python has several built-in functions that operate on a variable number of
arguments.
• Both are legal (and evaluate to what you think they do).
min(6,4)
min(3,4,1,6)
• Python makes it easy for programmers to define their own functions that
accept a variable number of arguments.
43
Variable Number of Arguments
• The unpacking operator * allows a function to accept a variable number
of positional arguments.
def mean(*args):
# Assumes at least one argument and all arguments are
numbers and Returns the mean of the arguments
tot = 0
for a in args:
tot += a
return tot/len(args)
• The name following the * in the argument list need not be args. It can be
any name.
44
Programming Exercise
• Implement a radians function that returns the radian equivalent of a
degree.
• Use this function to print a chart showing the radian equivalent of all
degrees ranging from 1° to 180°.
• Use two digits of precision for the results.
45
Scoping
def f( x ):
y = 1
x = x + y Function Definition
print('x =', x)
return x
x = 3
y = 2
z = f( x ) Main program code
print('z =', z) • Initializes variables
print('x =', x) • Makes a function call
print('y =', y) • Assigns a return of
function to variable z
46
Scoping
def f( x ): formal parameter
y = 1
x = x + y Function Definition
print('x =', x)
return x
x = 3
y = 2
z = f( x ) actual parameter Main program code
print('z =', z) • Initializes variables
print('x =', x) • Makes a function call
print('y =', y) • Assigns a return of
function to variable z
47
Scoping
def f( x ): formal parameter
y = 1
x = x + y Function Definition
print('x =', x)
return x
x = 3
y = 2
z = f( x ) actual parameter Main program code
print('z =', z) • Initializes variables
print('x =', x) • Makes a function call
print('y =', y) • Assigns a return of
function to variable z
• When run, what will the code print?
48
Scoping
x = 4
z = 4
x = 3
y = 2
49
Scoping
def f( x ): • At the call of f, the formal
y = 1 parameter x is locally bound to the
x = x + y value of the actual parameter x in
print('x =', x) the function body of f
return x
x = 3
y = 2 • The actual and formal parameters
z = f( x ) have the same name, but they are
print('z =', z) not the same variable
print('x =', x)
print('y =', y)
50
Scoping
def f( x ): • Each function defines a new name
y = 1 space, also called a scope
x = x + y
print('x =', x)
return x • The formal parameter x and the
x = 3 local variable y that are used in f
y = 2 exist only within the scope of the
z = f( x ) definition of f
print('z =', z)
print('x =', x)
print('y =', y)
51
Scoping
def f( x ): • The statement x = x + y within
y = 1
the function body binds the local
x = x + y x to 4.
print('x =', x)
return x
x = 3 • The assignments in f have no
y = 2 effect on the bindings of the names
z = f( x ) x and y that exist outside the
print('z =', z) scope of f.
print('x =', x)
print('y =', y)
52
How to think about Scoping?
1. At the top level, i.e., the level of the shell, a symbol table keeps track of
all names defined at that level and their current bindings
53
Variable Scope
54
Variable Scope
55
Variable Scope
56
Variable Scope
57
Variable Scope
58
Scoping
• In Python, one can always determine the scope of a name by looking at
the program text
59
Example Illustrating Scope Rules
def f(x): x = 3
def g(): z = f(x)
x = 'abc'
print('x =', x)
print('x =', x)
print('z =', z)
def h():
z = x
z()
print('z =', z)
x = x + 1
print('x =', x)
h()
g()
print('x =', x)
return g 60
History of the Stack Frames Associated
with the Code
• The first column contains the set of
names known outside the body of
the function f
▪ the variables x and z, and
▪ the function name f
61
History of the Stack Frames Associated
with the Code
• The assignment statement z =
f(x) first evaluates the expression
f(x) by invoking the function f
with the value to which x is bound.
62
History of the Stack Frames Associated
with the Code
• The names in the stack frame are:
▪ formal parameter x, not the x in
the calling context
▪ g, and h
63
History of the Stack Frames Associated
with the Code
• When h is invoked from within f,
another stack frame (column 3)
64
History of the Stack Frames Associated
with the Code
• Why does it not also contain x?
65
History of the Stack Frames Associated
with the Code
• In h, x occurs on the right-hand
side of an assignment statement
66
History of the Stack Frames Associated
with the Code
• If x is found, the value to which it is
bound is used.
67
History of the Stack Frames Associated
with the Code
• When h returns, the stack frame
associated with it goes away i.e.,
popped off the top of the stack
(see column 4)
68
A Helpful Analogy
• A helpful analogy is to think of
a stack of books
69
History of the Stack Frames Associated
with the Code
• The function g is now invoked
70
History of the Stack Frames Associated
with the Code
• When g returns, that frame is
popped (column 6).
71
History of the Stack Frames Associated
with the Code
• When f returns, the stack
frame containing the names
associated with f is popped,
getting us back to the
original stack frame
(column 7)
72
Example Illustrating Scope Rules
• What does the code print?
73
Example Illustrating Scope Rules
• When f returns, even though the variable g no longer exists, the object of
type function to which that name was once bound still exists
• z is bound to the value returned by f, and the function call z() is used to
invoke the function that was bound to the name g within f — even though
the name g is not known outside the context of f
74
Example Illustrating Scope Rules
• What does the code print?
x = 4
z = 4
x = abc
x = 4
x = 3
z = <function f.<locals>.g at 0x1092a7510>
x = abc
On my system
z = <function f.<locals>.g at 0x0000024138442040>
75
Example Illustrating Scope Rules
def f(): • What does the code print?
print(x)
def g():
print(x)
x = 1
x = 3
f()
x = 3
g()
76
Example Illustrating Scope Rules
def f(): • Prints 3 when f is invoked
print(x)
def g():
print(x) • Prints an error message when print
x = 1
x = 3 statement in g is encountered
f()
x = 3
g() • UnboundLocalError: local
variable 'x' referenced
before assignment
77
Example Illustrating Scope Rules
def f(): • The assignment statement
print(x) following the print statement
def g():
print(x) causes x to be local to g.
x = 1
x = 3
f() • Since x is local to g, it has no
x = 3 value when the print statement
g() is executed
78
Example Illustrating Scope Rules
def f(): • If an object is bound to a name
print(x) anywhere in the function body
def g(): (even if it occurs in an expression
print(x)
before it appears as the left-hand
x = 1
x = 3 side of an assignment), it is treated
f() as local to that function
x = 3
g()
79
Example Illustrating Scope Rules
• inside a function, can access a variable defined outside
80
Example Illustrating Scope Rules
81
Functions
• Functions provide decomposition and abstraction
82
Using Functions to Modularize Code
• As we implement more complicated functionality, it is convenient to split
functions into multiple functions, each of which does one simple thing
83
Using Functions to Modularize Code
def find_root_bounds(x, power):
"""x a float, power a positive int return low, high such that
low**power <=x and high**power >= x"""
low = min(-1, x)
high = max(1, x)
return low, high
84
Using Functions to Modularize Code
def bisection_solve(x, power, epsilon, low, high):
"""x, epsilon, low, high are floats epsilon > 0 low <= high and
there is an ans between low and high s.t. ans**power is within
epsilon of x returns ans s.t. ans**power within epsilon of x"""
ans = (high + low)/2
while abs(ans**power - x) >= epsilon:
if ans**power < x:
low = ans
else:
high = ans
ans = (high + low)/2
return ans 85
Using Functions to Modularize Code
def find_root(x, power, epsilon):
"""Assumes x and epsilon int or float, power an int,
epsilon > 0 & power >= 1 Returns float y such that y**power is
within epsilon of x. If such a float does not exist, it returns
None"""
if x < 0 and power%2 == 0:
return None #Negative number has no even-powered roots
low, high = find_root_bounds(x, power)
return bisection_solve(x, power, epsilon, low, high)
86
Using Functions to Modularize Code
• Is this version of find_root easier to understand than the original
monolithic implementation?
• Probably not!
87
Functions as Objects
• In Python, functions are first-class objects
• can be treated like objects of any other type, e.g., int or list
88
Functions as Objects
• Using functions as arguments allows a style of coding called higher-order
programming
89
Functions as Arguments
90
Functions as Arguments
91
Functions as Arguments
92
Functions as Arguments
93
Methods, Oversimplified
• Methods are function-like objects — can be called with parameters, and
can return values
• If s is a string, the find method can be used to find the index of the first
occurrence of a substring in s
▪ If s was 'abcbc', s.find('bc') would return 1
94
Programming Exercise
• Implement a fahrenheit function that returns the Fahrenheit equivalent
of a Celsius temperature. Use the following formula:
F = (9 / 5) * C + 32
• Use this function to print a table showing the Fahrenheit equivalents of all
Celsius temperatures in the range 0 – 100 degrees.
95
Programming Exercise
• Calculate the product of a series of integers that are passed to the function
product, which receives an arbitrary argument list.
• Test your function with several calls, each with a different number of
arguments
96