= 2
x = 3
y = x + y
x
for i in range(6):
= x + i
x
print('x =', x)
x = 20
The main goal of this module is to step back and review core concepts in programming: loops, conditionals, lists, functions.
Consider:
Variables have four aspects to them:
x
or immensely_pleased
above.
Let’s examine what happens when each line in the above program executes:
When the first line executes:
After the second line executes:
After the third line:
After the fourth:
After the fifth:
Then, one of the variables does have its value replaced:
Finally, one of the elements in the list gets replaced:
Now, there is a somewhat highly technical point to be made: - The “box” is what we’re using to conceptualize what a variable is, and how it behaves when we change it. - Generally, this is how you should think of it. - However, some books will present certain kinds of variables differently, with more detail. - Underneath the hood, in fact, string and list variables are a bit different.
So, for the sake of completeness, we’ll just point out this more detailed version:
Here:
s[2]
(3rd char in string).Let’s start with a simple example:
Let’s look at this in steps:
First, start by noticing the chunks of code:
Next, walk through the execution of the first chunk, and notice that the value of x
is what’s used later:
x
and y
, then do so.
x = x + y
and say to yourself: “First, let’s look at the right side, and the values of x
and y
now”.x
and y
.x
(5, in this case) that replaces what was there (which was 2).Then get down to the iterative level and execute iteration by iteration:
i x
Before loop starts: 5
After first iteration 0 5
After i is 1 1 6
After i is 2 2 8
After i is 3 3 11
After i is 4 4 15
After i is 5 5 20
Finally, there’s the print
statement:
Next, let’s look at reading a complex conditional:
age = 17
maximum_feasible_age = 120
voting_age = 18
berlin_age = 16
toronto_age = 19
washington_age = 21
if age >= maximum_feasible_age or age < 0:
print('That age is not realistic.')
else:
if age >= voting_age:
print('This person can vote in the USA.')
if age > toronto_age:
print('This person can buy a beer in Toronto.')
if age > washington_age:
print('This person can buy a beer in Washington, DC.')
elif age >= berlin_age:
print('This person can buy a bottle of beer in Berlin.')
else:
print('This person is a minor.')
We’ll do this in steps, working from the “outside going in”:
The conditions depend on the variables above.
The boolean expression maximum_feasible_age or age < 0
fails, so we move on to the else
, which executes.
Then, working inwards, we examine and see that the else
statement’s code block is itself a big conditional:
if
condition fails (age >= voting_age
is False
) and so execution proceeds into the elif
block:elif
statement is True
, and so its body (a print
statement) executesThis example illustrates how critical it is to make sure the indentation is correct. For example, consider this variation:
Moving the indentation inward changes the logical execution of the series of conditionals.
Type up the above in execution_practice2.py
. There are some logical errors with the set of conditionals: find them and fix them.
Hints:
Check your results with ages 15, 16, 17, 18, 19, 20, and 21.
As you’ve seen before, there’s often more than one way to solve any given problem.
In execution_practice3.py
, rewrite the set of conditionals to work (give the same output for a given age
) with no nested conditionals. You may use as many if
, elif
, and else
statements as you need, but none may be nested.
Hint:
if
statements can generally be produced, alternatively, using and
and or
in the condition of a single if
statement.As before, check your results with ages 15, 16, 17, 18, 19, 20, and 21.
Consider the following program:
def printword(n):
if n == 1:
print('one')
elif n == 2:
print('two')
elif n == 3:
print('three')
elif n == 4:
print('four')
else:
print('cannot handle n > 4')
printword(1)
printword(2)
printword(3)
printword(4)
printword(5)
In conditional.py
, rewrite the function so that it does the same thing but without using any elif
statements.
Consider this example:
Let’s look at the execution step by step:
print
statement, followed by the first function call (or function invocation). At this point, execution enters the function:Consider this program:
def print_two_xs():
print('xx')
def print_three_ys():
print('yyy')
def print_more():
print_two_xs()
print_three_ys()
print('z')
print('start')
for i in range(8):
if i % 3 == 0:
print_two_xs()
elif i % 3 == 1:
print_three_ys()
else:
print_two_xs()
print_three_ys()
print_more()
print('end')
Examine and mentally execute the above program. Then confirm by writing it up in execution_practice5.py
.
Here’s an example:
def print_stuff(n):
print('n =', n)
n = 2*n
print('twice n =', n)
n = n // 4
print('half n =', n)
m = 4
print(m)
print_stuff(m)
print(m)
n
gets its value from the argument variable://
is the integer division operator. Later in the function, the parameter variable gets its value changed:It’s important to realize that we could have named the argument variable n
as well:
Any code inside the function that uses or modifies n
affects only the parameter variable n
(the n
inside the function and not the n
outside the function).
Let’s emphasize one more thing by looking at:
def print_stuff(n):
print('n =', n)
n = 2*n
print('twice n =', n)
n = n // 4
print('half n =', n)
print('m =', m) # Trying to access m
m = 4
print(m)
print_stuff(m)
print(m)
print('n =', n) # Trying to access n
Type up the above in variable_access.py
. Can you explain why half of the original n
is calculated as n // 4
?
You will notice that m
is accessible in the function whereas the parameter variable n
is not accessible outside. This is a topic (called scope) that we’ll address in Unit 2.
Let’s look at an example:
incr()
function occurs: j = incr(i)
i
is copied into parameter variable n
:m
becomes 6, which is returned when the return
statement executes:j
has the value 6.k = incr( incr( incr(j) ) )
which calls to incr()
with argument 6, returning 7, which results in k = incr( incr(7) )
k = incr( incr( 7 ) )
calls incr()
with argument 7, which returns 8, which results in k = incr( 8 )
k = incr( 8 )
similarly results in k = 9
return
statement can have expressions. Which means we can shorten incr()
to:return
statement itself:This is a shorter way of writing
Consider a function with multiple returns:
def strange(n):
print('start-of-strange')
if n < 0:
return 0
elif n == 0:
return 1
else:
s = 1
for k in range(n+1):
s = s + k
return s
print('end-of-strange')
print(strange(-3))
print(strange(0))
print(strange(3))
Note: In the first call to the function strange()
, the parameter n
will have the value -3. - In this case, we see ‘start-of-strange’ printed. The if
condition is true, which means the first return
executes:
def strange(n):
print('start-of-strange')
if n < 0:
return 0 # function returns here
elif n == 0:
return 1
else:
s = 1
for k in range(n+1):
s = s + k
return s
print('end-of-strange')
For each of the three calls to the function strange(), can you tell whether ‘end-of-strange’ gets printed? Then confirm by typing it up in strange_example.py
.
Consider
def add_one(n):
n = n + 1
print('incr: n=', n)
def list_add_one(A):
for k in range(0, len(A)):
A[k] = A[k] + 1
print('list_incr: A=', A)
p = 3
add_one(p)
print(p)
B = [1, 2, 3]
list_add_one(B)
print(B)
Type up the above in list_example.py
.
add_one()
function has no effect on the variable p
, since the value in p
gets copied into n
. The parameter variable n
does get 1 added (as the print
in add_one()
confirms.print(B)
shows that the elements of B
have 1 added to each of them.B
’s are copied into parameter variable A
, then the variable A
has the special token.Trace through each iteration of the loop in the function list_or()
, showing x
, k
, and each A[k]
. Then confirm in list_example2.py
.
And another example for practice:
def within1(x, y):
# Write your code here to return True or False
# Return True if the difference between x and y is 1 or less
def first_diff(A, B):
k = 0
while (k < len(A)) and (within1(A[k], B[k])):
k = k + 1
if k == len(A):
return -1
else:
return k
X = [1, 2, 3, 4]
Y = [2, 2, 3, 3]
Z = [1, 1, 1, 4]
print(first_diff(X,Y)) # Should print -1
print(first_diff(X,Z)) # Should print 2
The function first_diff()
is intended to take two lists, compare elements in the same positions, and identify the first position where the two lists differ by more than 1. If no such difference exists, the function should return -1.
In list_example3.py
, complete the code in the within1()
function so that it returns True
only when the difference between x
and y
is 1 or less, i.e. True
when x=1
and y=2
, or when x=4
and y=3
, or when x=5
and y=5
. After that, trace through the iteration in the while-loop.
Functions are very useful for four different reasons:
Code written in a function can be re-used. For example, compare:
X = [1, 3, 5, 7]
total = 0
for k in X:
total += k
avg = total / len(X)
print(avg)
Y = [2, 4, 6, 8, 10]
total = 0
for k in Y:
total += k
avg = total / len(Y)
print(avg)
with
def mean(A):
total = 0
for k in A:
total += k
return total / len(A)
X = [1, 3, 5, 7]
print(mean(X))
Y = [2, 4, 6, 8, 10]
print(mean(Y))
The second reason is, as this example shows:
(You can imagine what the functions incr()
and diff()
do.) Another example showing compactness with functions:
A long program broken up into functions will make the program more readable and therefore more easily understood. The biggest reason, perhaps, is that it has become one of two important ways by which multiple programmers use each others’ code.
As an example, you have used functions in drawtool
and Python functions like math.random()
.
How do you know when to create functions vs. writing long code? There are no rules. The judgement comes with practice. Generally, tiny computations like increment don’t need functions. Any significant computation that is likely to be re-used should probably be in a function. Also, use functions when when doing so improves readability.
Full credit is 100 pts. There is no extra credit.
Write a function list_max
that takes one argument, a list. The list will contain numbers (ints and floats). Your function should return the biggest number in the list.
Write another function list_min
that takes one argument, a list. The list will contain numbers (ints and floats). Your function should return the smallest number in the list.
Do not use built-in min
or max
functions (or any libraries).
Submit both functions in one file, list_min_max.py
.
Write a function list_remove
that takes two arguments: the first argument is a list, the second argument could be anything.
Do not use the built-in .remove
function (or any other function that removes elements from a list).
Examples:
list_remove([3, 4, 7], 7)
returns [3, 4]
.list_remove([3, 4, 7], 8)
returns [3, 4, 7]
.list_remove(['A', 'B', 'B', 'A'], 'A')
returns ['B', 'B', 'A']
.Submit as list_remove.py
.
Write a function string_count
that takes two arguments, both are strings.
Do not use the built-in .count
function or the built-in .find
function.
Examples:
string_count('verbatim', 'r')
should return 1
.string_count('Mississippi', 's')
should return 4
.string_count('After the storm passed, they sailed.', 'the')
should return 2
.Submit as string_count.py
.
Write a function string_strip
that takes as input a string and removes space ' '
and newline '\n'
characters from the beginning and the end of the string, to whatever extent consecutive instances of either character exist. (You cannot actually modify a string, but your function should return a new string with this operation effectively performed.)
Examples:
string_strip(" \n great! ")
returns string "great!"
.string_strip("ok ")
returns string "ok"
.string_strip(" \n what's next?\n \n")
returns string "what's next?"
.Submit as string_strip.py
. Do not use the built-in .strip
function.
Write a function string_split
that takes takes two arguments, both strings. The function should “split” the first string on the second string, and return a list of the substrings, identical to the .split
function.
Examples:
string_split('everything rings falser, a little metallic', ' ')
returns ['everything', 'rings', 'falser,', 'a', 'little', 'metallic']
string_split('the finer things', 'er')
returns ['the fin', ' things']
string_split('the finer things', 'the')
returns ['', ' finer things']
Submit as string_split.py
. Do not use the built-in .split
function.