Preparation

Create a file called loops_lab.py and put all of your code for today inside this file.

Exercise 1

Consider the following loop.

count = 0
for i in range(10):
    if i % 3 == 0:
        count = count + 1
    
    # print("Currently, i =", i, "and count =", count)

print("The final count is:", count)

a. Predict what the value of count is when it is printed.

b. Verify your prediction by copying and pasting the code into your loops_lap.py file and running it via the terminal.

c. Uncomment the print statement making sure that it is horizontally aligned with the if and rerun the code to see the intermediate steps of the loop.

d. Try changing the 10 passed to range to several other numbers and make sure it does what you expect.

e. What does the final count represent? Discuss with your partner(s).

Exercise 2

Consider the following loop.

integers = [5, 9, -17, 2, 4, 4, 8, 3, -1]
count_even = 0
count_odd = 0

for num in integers:
    if num % 2 == 0:
        count_even = count_even + 1
    else:
        count_odd = count_odd + 1

    # print("Currently, num =", num, ", count_even =", count_even, ", and count_odd =", count_odd)

print("The final even / odd counts are:", count_even, "/", count_odd)

a. Predict what the values of count_even and count_odd are when they are printed.

b. Verify your prediction by copying and pasting the code into your loops_lap.py file and running it via the terminal. (Be sure to comment out other code that may be in the file.)

c. Uncomment the print statement and rerun the code. (It should be horizontally aligned with else:.)

d. Try changing the numbers in integers to see how the execution of the loop changes.

Exercise 3

Consider the following loop.

old_list = [10, "the", -7, 17.5, "quick", "brown", 19, "fox"]

new_list = []
for element in old_list:
    if type(element) == str:
        new_list.append(element)

    # print("Currently, element =", element, " and new_list =", new_list)

print("The final values of new_list are:", new_list)

a. Predict what the value of new_list is when it is printed.

b. Verify your prediction by copying and pasting the code into your loops_lap.py file and running it via the terminal. (Be sure to comment out other code that may be in the file.)

c. Uncomment the print statement and rerun the program to see the intermediate steps.

d. Try changing the elements of old_list to see how the execution of the loop changes.

Exercise 4

Rewrite the code from exercise 3 so that it is a function named extract_strings that takes a list as a parameter and returns a copy of the same list that contains only the strings of the original list.

Exercise 5

Consider the following loop.

old_list = [10, "the", -7, 17.5, "quick", "brown", 19, "fox"]

new_list = []
index = len(old_list) - 1
while index >= 0:
    # print("Currently, index =", index, ", old_list[index] =", old_list[index], ", and new_list =", new_list)
    new_list.append(old_list[index])
    index = index - 1

print("The final values of new_list are:", new_list)

a. Predict what the values of new_list are when they are printed.

b. Verify your prediction by copying and pasting the code into your loops_lap.py file and running it via the terminal. (Be sure to comment out other code that may be in the file.)

c. Uncomment the print statement and rerun the code to watch the intermediate steps.

d. Try changing the elements of old_list to see how the execution of the loop changes.

e. Explain in your own words what this code is doing. Discuss with your partner(s).

Exercise 6

Consider the following loop.

old_list = ["hello", "world", "foo", "bar", "baz"]

new_list = []
index = 0
while index < len(old_list):
    # print("Currently, index =", index, ", old_list[index] =", old_list[index], ", and new_list =", new_list)
    new_list.append(old_list[index])
    index = index + 2

print("The final values of new_list are:", new_list)

a. Predict what the values of new_list are when they are printed.

b. Verify your prediction by copying and pasting the code into your loops_lap.py file and running it via the terminal. (Be sure to comment out other code that may be in the file.)

c. Uncomment the print statement and rerun the code.

d. Try changing the elements of old_list to see how the execution of the loop changes.

e. Notice that new_list always consists of the evenly indexed elements of old_list. Modify the code so that new_list consists of the elements in the odd indices instead.

Exercise 7

Rewrite the code from exercise 6 so that it is a function named extract_odd_elements that takes a list as a parameter and returns a copy of the same list that contains only the strings of the original list.

Exercise 8

a. The range(start, stop) function is pretty helpful. Try executing the following in the REPL to make sure you understand what sequence it is returning.

>>> list(range(0, 5))
>>> list(range(3, 10))
>>> list(range(-7, 4))

Note that range(0,5) returns an object that represents the sequence 0, 1, 2, 3, 4, however, it is not explicitly a list but it can be type casted to the list type (like above) if needed. To see why range is implemented in this way, consider the following two for loops:

for x in list(range(10000)):
    print(x)
for x in range(10000):
    print(x)

In the first example, the list [0, 1, 2, ... , 9999] must be constructed in memory before a single line of code in the for loop is executed. This can take up a lot of memory and require a lot of preprocessing to construct the list. However, in the latter example, the list is not explicitly constructed and the for loop will only read one element from the sequence out at a time. This can be much more efficient in many cases.

b. The range function also has an optional third parameter usually called the “step”. Try experimenting with it in the REPL to make sure you understand what it is doing.

>>> list(range(0, 5, 1))
>>> list(range(3, 10, 2))
>>> list(range(10, 0, -1))

c. As an exercise, let’s try implementing a function that is similar to the range function but always returns a list. Add a function named my_range to your lab file that takes three integers start, stop, and step as parameters and returns a list that contains the integers starting at start and counting up to but not including the integer at stop.Your function should also make steps of size step. Furthermore, you should write your function without using the range function.

Below are a few example executions of the function.

>>> my_range(0, 5, 1)
[0, 1, 2, 3, 4]
>>> my_range(3, 10, 2)
[3, 5, 7, 9]
>>> my_range(-7, 4, 3)
[-7, -4, -1, 2]