October 25 - A deeper dive into Python

Welcome to the third lesson of Woodlands Computer Science! We’ll be taking a deeper dive into Python in this lesson by exploring for loops, while loops, lists, and dictionaries.

Review

In the last meeting, we covered:

Last week’s interactive lesson is available at https://woodlands.codes/group-a/2021/10/17/lesson-1.html.

Today, we’ll be covering

While loops

While loops are a type of loop in Python that allow you to run a block of a code while an expression/condition is satisfied (i.e. evaluates to True).

The format of a while loop is as follows:

while <expression>
    <code>

The below code presents an example of a while loop in Python.

counter = 0 while counter <= 6: print("The counter is equal to " + str(counter)) counter = counter + 1 print("Finally, the counter is equal to " + str(counter))

We begin by defining a variable called counter. Then, the while loop’s condition is counter <= 6, so the code that is indented as part of the while loop will run while counter <= 6. Inside the loop, counter is incremented and its value is printed to the output.

Note that <= means “less than or equal to”

The code below presents a slightly more complicated usage of while loops.

name = input() while name != "Vishnu": print("The name is not Vishnu! It is " + name + ".") name = input() print("The name is Vishnu!") ##### Jeffrey Marcus Max Nathan Vishnu Raymond

Notice how The name is not Vishnu! It is Raymond. is never printed to the output since the while loop terminates before Raymond is taken from the input and printed.

Changing the flow of a while loop

The break and continue keywords can be used inside a while loop to change the flow of the loop.

break immediately terminates the loop and the first statement after the loop is executed.

continue immediately skips the rest of the statements inside the loop and the loop is executed from the start.

Here’s a diagram that demonstrates the difference between break and continue

For loops

For loops are a type of loop that execute a block of code inside the loop for each element in an iterable. An iterable is something that has elements that can be iterated.

Iterate means go through or go over. Imagine you have a deck of cards. By going through each card, you are iterating the deck of cards. Examples of iterables include lists and dictionaries. We’ll be going over the basics of lists and dictionaries in this lesson. But first, let’s talk about for loops!

The format of a for loop is as follows:

for <variable> in <iterable>:
    <code>

Where <variable> contains the current element of the iterable.

You can use the range(start, stop, step) function to generate an iterable containing numbers from start (inclusive) to stop (exclusive) with the step step. A negative value for step indicates that the numbers will be generated in reverse order (stop must be less than start in that case).

Note that start and step are optional. If only one value is provided, then it will be assumed to be stop. If two values are provided, then they will be assumed to be start and stop, in that order.

If you’ve taken math, you can relate the range(start, stop, step) function with sigma notation.

$\large{y=\sum_{x=0}^{10} x^2}$

Note that \(y = 385\).

The notation above would have the following for-loop equivalent.

y = 0 # We put 11 as the stop since stop is exclusive (i.e. this iterates from 0-10) for i in range(0, 11): y += i ** 2 print(y)

Here’s an example of using range with a reverse step.

for i in range(10, -1, -1): print(i)

Activity

Write a program to iterate from start (inclusive) to stop (inclusive), where start and stop are two variables whose values are provided by the user. (Hint: use the input() function you learned about last week!).

Then, inside the for loop, output the current number!

Example (>>> denotes user input, everything else is program output):

Enter a starting number.
>>> 2 
Enter a stopping number.
>>> 7
2
3
4
5
6
7

Now, try writing the same program using a while loop!

Lists

Lists are a data structure in Python that allow you to store elements. Lists are also an iterable, meaning you can use for loops to iterate the list.

Lists are defined using square brackets and can be assigned to a variable. You can also optionally place elements inside a list when it is defined through comma-separated elements. Below is an example.

names = ["Jeffrey", "Marcus", "Nathan", "Vishnu", "Max", "Raymond"] print(names)

You can use for loops to iterate a list! :)

names = ["Jeffrey", "Marcus", "Nathan", "Vishnu", "Max", "Raymond"] for name in names: print("The current name is " + name)

To get certain elements of a list, you can use slice notation.

Below is an explanation of the different ways you can use slice notation to get elements of a list.

Note that lists are 0-indexed, meaning the first element will have an index of 0.

Say our list is

names = ["Jeffrey", "Marcus", "Nathan", "Vishnu", "Max", "Raymond"]
Slice Description Example
names[i] Returns the element in names with the index i. names[0] returns "Jeffrey"
names[start:stop] Returns a new list with elements from the original list between the indexes start (inclusive) and stop (exclusive). names[2:5] returns ["Nathan", "Vishnu", "Max"]
names[start:] Returns a new list with elements from the original list from the index start to the end of the list. names[3:] returns ["Vishnu", "Max", "Raymond"]
names[:stop] Returns a new list with elements from the original list from the beginning of the list to stop (exclusive). names[:5] returns ["Jeffrey", "Marcus", "Nathan", "Vishnu", "Max"]
names[start:stop:step] Returns a new list with elements from the original list between the indexes stop (inclusive) and start (exclusive) with the step step. names[1:5:2] returns ["Marcus", "Vishnu"]


You can also assign list slices. We’ll be going over this in the example.

To count from the end of a list, you can use negative indices, where the last element in a list is at the index -1, the second last is at the index -2, and so on.

Below are some common built-in methods and functions you can use on Python lists, where the name of the list is current_list.

Method Description
current_list.append(element) Adds element to the end of the list.
del current_list[i] Deletes the element in the list with index i.
current_list.insert(i, element) Inserts element into the list at the desired index i.
current_list.index(element) Returns the first index of the occurrence element in the list. If the element is not found, throws a ValueError.
current_list.count(element) Returns the number of occurrences of element in the list.
current_list.clear() Removes all elements in the list.
current_list.extend(iterable) Adds every element of an iterable to the end of the list.
current_list.sort(reverse=False, key=function) Sorts the list based on the value returned by function when each element is passed into it; optionally sorts in reverse order.
current_list.reverse() Reverses the list
len(current_list) Returns the length (number of elements) of the list
element in current_list Returns a boolean whether element exists in the list


Note that this isn’t a comprehensive list

Here’s an example of using slicing, common list methods, and using a for loop to iterate through a list!

names = ["Jeffrey", "Marcus", "Nathan", "Vishnu", "Max", "Raymond"] names.append("Mr. Dutton") # Remember types? print("There are " + str(names.count("Raymond")) + " occurrences of Raymond in the list.") # Why is it printing the names in reverse? for name in names[::-1]: print("The current name is " + name) del names[-1] print("Max can be found at index " + str(names.index("Max"))) print(names[3:1:-1]) del names[-3:] # Uh oh! Vishnu, Max, and Raymond are gone! print(names) names.extend(["Vishnu", "Max", "Raymond"]) # Now they're back! print(names)

Dictionaries

Dictionaries are a data structure in Python that allow you to store key-value pairs.

You can access values in Python using their keys, but not vice-versa. This means you cannot have duplicate keys.

Dictionaries are great to use when you have labelled data.

You can also relate dictionaries to mathematical functions (as you may have learned in the grade 11 mathematics course). Relate the keys of a dictionary to the domain of a function and the value to the range of a function.

Dictionaries are defined using curly brackets, colons between the key and the value, and commas to separate pairs of keys and values. Take a look at the below example.

people_grades = { "Vishnu": 11, "Nathan": 12, "Max": 12, "Raymond": 12, "Jeffrey": 12, "Marcus": 11 } print(people_grades)

You can use keys to access values from dictionaries. Square brackets are used, similar to slice notation for lists. Take a look at the example below.

people_grades = { "Vishnu": 11, "Nathan": 12, "Max": 12, "Raymond": 12, "Jeffrey": 12, "Marcus": 11 } print("Marcus is in grade " + str(people_grades["Marcus"]))

Similar to lists, dictionaries are iterables meaning you can use for loops to iterate a dictionary. The variable after the word for in the loop will represent the key. The below code presents an example.

people_grades = { "Vishnu": 11, "Nathan": 12, "Max": 12, "Raymond": 12, "Jeffrey": 12, "Marcus": 11 } for name in people_grades: print(name + " is in grade " + str(people_grades[name]))

To add a new element to a dictionary, you can use slicing! Take a look at the below example.

people_grades = { "Vishnu": 11, "Nathan": 12, "Max": 12, "Raymond": 12, "Jeffrey": 12, "Marcus": 11 } people_grades["Mr. Dutton"] = "Teacher" print(people_grades)

Below are some common built-in methods, functions, and slicing examples you can use on Python dictionaries, where the name of the dictionary is current_dict.

Method Description
current_dict[k] Returns the value of the element in the dictionary with the key k
del current_dict[k] Deletes the element in the dictionary with key k.
current_dict.get(k, default) Returns the value of the element in the dictionary with the key k. If the key is not found, default is returned. If default is not provided, None is returned.
current_dict.clear() Remove all elements from the dictionary
current_dict.items() Returns an iterable (similar to a list) with each element being (key, value)
current_dict.keys() Returns an iterable (similar to a list) of the dictionary’s keys
current_dict.values() Returns an iterable (similar to a list) of the dictionary’s values
len(current_dict) Returns the number of keys in the dictionary.
key in current_dict Returns a boolean whether key exists in the dictionary


Note that this isn’t a comprehensive list

Here is an example of using dictionary methods, functions, and slicing!

people_grades = { "Vishnu": 11, "Nathan": 12, "Max": 12, "Raymond": 12, "Jeffrey": 12, "Marcus": 11 } people_grades["Mr. Dutton"] = "Teacher" print("Peoples' grades:", list(people_grades.values())) # Mr. Dutton isn't a student! del people_grades["Mr. Dutton"] student = input() if student in people_grades: print(student + "'s grade is " + str(people_grades[student])) else: print(student + " is not a WCS exec!") ##### Jeffrey

Advanced Activity

If you think you’ve got a good grasp of dictionaries and lists, try solving the following problem:

Given a list consisting of integers, print a dictionary such that the keys are the values of the list, and the values are the frequencies of the value in the list. The list will be provided in the variable nums.

nums = [1, 3, 4, 5, 1, 2, 7, 8, 3, 4, 5, 6, 1, 2, 8, 1, 1, 7, 8]

For this case, the output should be

{1: 5, 3: 2, 4: 2, 5: 2, 2: 2, 7: 2, 8: 3, 6: 1}

As an example, note that the element 1 appears 5 times in nums. Try creating your own test cases as well!

This problem is an adaption of https://binarysearch.com/problems/High-Frequency

Solution
nums = [1, 3, 4, 5, 1, 2, 7, 8, 3, 4, 5, 6, 1, 2, 8, 1, 1, 7, 8] freq = {} for element in nums: freq[element] = freq.get(element, 0) + 1 print(freq)