Lecture Notes 10: More Loops
Before we start: testing in Replit
Let's see the output of an "almost correct" submission for HW02:
(Student "frankpablo" in Replit)
Errors:
An "erroneous expected output from a function call" (IMPORTANT)
An "erroneous expected output for a print test" (not important)
Three concepts: None, in, and is
None
If one does not explicitly return a value in a vunction, the default "return" is
None.
None is a python reserved word, used to define a "null value", or "the absence of a value".
- None is not 0
- None is not False
- None is of type NoneType
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | def main():
num = 5
# If I try to get a return value from no_return
ret_value = no_return(num)
# I get None
print (ret_value)
def no_return (num):
print("only displays num: ", num)
if __name__ == "__main__":
main()
|
Try it
Here
in
The
Membership Operator in returns
True if a sequence with the specified value is present in the object.
Example:
1
2
3 | word = "abracadabra"
print ("ada" in word) # prints True
print ("aaa" in word) # prints False
|
One can also ask the opposite!
1
2
3 | sentence = "the password is 'Cat'"
print ("Yak" not in sentence) # prints True
print ("Cat" not in sentence) # prints False
|
is
The Equality operator (==) compares the values of the operands on either side and verifies that they are the same.
The Inequality operator (!=) compares the values of the operands on either side and verifies that they are the same.
The is operator checks whether both the operands refer to the same object or not (they are located in the same memory location and therefore also have the same value).
The is not operator checks whether both the operands refer to different objects or not (they are located in different memory locations... and might or might not have the same value).
We will check a clear visual representation of this once we see lists and move on to classes and objects.
Check out the nice summary on
Operators.
Recap: range
the usage of range is:
range(start, stop, step)
this function returns a sequence of numbers, starting from the indicated start value (or 0 by default), incrementing by the step value (1 by default), and stopping before the indicated stop value.
Activity 1 [5 minutes]:
Form groups and, in your Replit Scratchpad, try all of the following ranges inside a for loop (by replacing the section marked as
< range here >):
for i in <range here>:
print(i, end=" ")
range(10)
range(0, 10)
range(1, 10)
range(1, 10, 2)
range(1, 10, 3)
range(-10)
range(-10, 0)
range(10, 3)
range(10, 3, -1)
range(10, 3, -2)
range(10.5)
for loops, the in operator, and strings
One of the benefits of the versatility of python and the in operator is that we can do the following:
def main():
word = "evolutionarily"
vowels = "aeiou"
num_v = 0
num_c = 0
for char in word:
if char in vowels:
print(char,"is a vowel")
num_v+=1
else:
print(char,"is a consonant")
num_c+=1
print("The word {:s} has {} vowels and {} consonants".format(word, num_v, num_c))
if __name__ == "__main__":
main()
Try it out
here
Reviewing while and for
Let's first build a couple of simple loops:
Activity 2 [2 minutes]:
In your Replit Scratchpad, write a for loop that prints all the even numbers from 10 to 0 (in a single line)
Now, write a while loop that prints all the odd numbers from 11 to 1 (in a single line)
Now, let's convert while loops to for loops and vice-versa:
Activity 3 [2 minutes]:
First, analyze the following code and explain what it does (and how!)
Then, open up your scratch pad (Replit) and transform the following While Loop into a For Loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | def main():
num = 5
fac = mystery_func1(num)
print("The result for {:d} is {:d}".format(num, fac))
def mystery_func1(x):
mult = 1
while x > 1:
mult *= x
x-=1
return mult
if __name__ == "__main__":
main()
|
Activity 4 [2 minutes]:
First, analyze the following code and explain what it does (and how!)
Then, open up your scratch pad (Replit) and transform the following For Loop into a While Loop
def main():
word = "evolutionarily"
li_counts = vowel_counts(word)
print("The vowel counts in {:s} are {}".format(word, li_counts))
def vowel_counts(word):
wrd_low = word.lower()
vowels = "aeiou"
v_count = 0
# note the cool way to iterate chars over a string!
for char in wrd_low:
if char in vowels:
idx = vowels.find(char)
v_count += 1
return v_count
if __name__ == "__main__":
main()
Nested Loops
Nested loops are loops done inside of other loops.
They are useful for many reasons, but a clue that we'll probably need one is when you have multiple dimensions to work through:
- For each student, get the average of all their grades
- For each word in a paragraph, check each one of its letters
- For each inner-list in an outer list, print out the inner-list's elements
- etc
Notation for nested loops
There is nothing to add!
You already know how to write a loop, simply write a loop inside a loop!
Activity 5 [2 minutes]:
In your Replit Scratchpad, write a for loop that prints all the numbers from 1 to 5
Now, instead of the print statement inside the for loop, insert a properly indented for loop that prints the numbers 1 to 7
The important thing to note is that the external for loop causes the internal one to run its code several times.
Let's see some examples:
Example 1: a number pyramid
We wish to generate the following structure:
First attempt (no nesting)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | def main():
pyramid() # prints 5 levels of numbers
def pyramid():
for j in range(1):
print(j+1, end=" ")
print()
for j in range(2):
print(j+1, end=" ")
print()
for j in range(3):
print(j+1, end=" ")
print()
for j in range(4):
print(j+1, end=" ")
print()
for j in range(5):
print(j+1, end=" ")
if __name__ == "__main__":
main()
|
Look at the code
Here
Activity 6 [2 minutes]:
In the same way we asked before, do you notice any code that is repeated?
Attempt 2: Nesting!
Let's use out old friend:
a loop to take advantage of "automated repetition!"
Steps:
- First, what is every repetition dependent on (what changes in each repetition)?
- Is this something we can use a variable for?
- If so, can we write a loop that viaries this variable?
Let's try it:
Steps:
- First, surround a single block of code ( the one that was "repeated") in a for loop (you can try a while later)
- Replace the changing parameter for the loop variable (let's use i)
- Set the varying range according to the initial range of desired values (1, 2, 3, 4, 5)
You should end up with something like this:
1
2
3
4
5
6
7
8
9
10
11
12 | def main():
pyramid() # prints 5 levels of numbers
def pyramid():
for i in range(1,5):
for j in range(i):
print(j+1, end=" ")
print()
if __name__ == "__main__":
main()
|
You can see it in action
Here!
Attempt 3: Nesting using input parameters
For greater versatility, we can change the number of times we repeat the outer loop based on some input parameter!
1
2
3
4
5
6
7
8
9
10
11
12 | def main():
pyramid(7) # prints <argument> levels of numbers
def pyramid(lim):
for i in range(1,lim+1):
for j in range(i):
print(j+1, end=" ")
print()
if __name__ == "__main__":
main()
|
Check it out
Here!
Homework
[Due for everyone]
Assignment 03 is out (Due 02/18 at 5PM)
[Optional]
ZyBooks Sections 4.8 - 4.12