AddisCoder 2023: Week 2
July 25, 2023
Taught by Alex Krentsel.
Start with slides!
The three most missed problems were #13, #20, and #21. Let's solve them together!
# Question #13: What is the printed output of the following code snippets? If there is an infinite loop, write "Infinite".
# 13a
num = 0
while num < 6:
if num % 2 == 0:
print(num)
num += 1
0 2 4
# 13b
num = 0
if num % 2 == 0:
while num < 6:
print(num)
num += 1
# 13c
num = 0
if num % 2 == 0:
while num < 6:
print(num)
num += 1
0 1 2 3 4 5
# Question #20: Write a function `countCharacters(word)` that returns the number of times each character appears in the word.
def countCharacters(word):
characters = {}
for char in word:
if char in characters:
characters[char] += 1
else:
characters[char] = 1
return characters
countCharacters("hello")
{'h': 1, 'e': 1, 'l': 2, 'o': 1}
# Question #21: Use a forloop to create a new list that contains the original values doubled.
# Example: lst = [1, 2, 3, 4] --> [2, 4, 6, 8]
def listDouble(lst):
doubled = []
for num in lst:
doubled.append(num * 2)
return doubled
listDouble([1, 2, 3, 4])
[2, 4, 6, 8]
Just like real-world dictionaries, these are used for lookup. You have some key (ex: a word) and you want to find the associated value (ex: a definition). Let's walk through the slides first.
# For creating dictionaries, use curly braces:
gradebook = {}
print(type(gradebook))
print(gradebook)
<class 'dict'> {}
# We add key:value pairs to our dictionary using square brackets on the *left* of the equals sign.
print(gradebook)
print("Adding new key:value pair.")
gradebook["alex"] = 95
print(gradebook)
{} Adding new key:value pair. {'alex': 95}
# You can get the value associated with a key by using brackets *not* to the left of an equal sign:
print(gradebook["alex"])
95
# What happens if you try to lookup a key that doesn't exist in the dictionary? Error!
print(gradebook)
print("Daniel's score:", gradebook["daniel"])
{'alex': 95}
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[6], line 3 1 # What happens if you try to lookup a key that doesn't exist in the dictionary? 2 print(gradebook) ----> 3 print("Daniel's score:", gradebook["daniel"]) KeyError: 'daniel'
# To avoid this issue, we can check if a dictionary contains something using `in`
if "daniel" in gradebook:
print("Daniel's score:", gradebook["daniel"])
else:
print("daniel is not in the dictionary")
daniel is not in the dictionary
# To iterate over dictionary keys, use the forloop syntax. It works for dictionaries automatically!
for key in gradebook:
print("name:", key, ", grade:", gradebook[key])
name: alex , grade: 95
# Common pattern when building dictionaries as counters:
counter_dict = {}
word = "horse"
if word in counter_dict:
counter_dict[word] = counter_dict[word] + 1
else:
counter_dict[word] = 1
print(counter_dict)
{'horse': 1}
We saw some common mistakes with functions on the exam and when walking around during lab. Let's clarify them here.
# (1) Defining vs Calling Functions
# Defining a function:
def invert_string(s):
new_string = ""
for i in range(len(s) - 1, -1, -1):
new_string = new_string + s[i]
return new_string
# Running this block _creates_ the function, but nothing actually gets run because the function hasn't been called.
# Calling a function:
print(invert_string("hello"))
# Running this block actually runs the function and prints the output.
olleh
# (2) Return vs Print
# An "expression" is any statement that evaluates to a value. For example, `1 + 1` is an expression that evaluates to `2`.
# Functions are also expressions. For example, `len("hello")` is an expression that evaluates to `5`.
def fun_func():
return 5
# The `return` statement tells Python what value the function should evaluate to. In this case, the function evaluates to `5`.
print(fun_func())
5
# Not all functions evaluate to something! You can tell because they have no `return` statement. For example:
def void_func():
x = 1 + 1
# This function doesn't return anything. It just runs some code. If we try to print the output of this function, we get `None`.
print(void_func())
None
# void_func() isn't very useful, but the more common case is when you want to print something inside a function. For example:
def print_func():
print("hello")
# This function doesn't return anything. It just prints something. If we try to print the output of this function, we get `None`.
print(print_func())
hello None
# So, we use `print` to print things to the console, and we use `return` to return values from functions.
# So often times, there's two ways to write a function if you want to show something on
# the screen: one that returns a value, and one that prints a value.
def return_sum(a, b):
return a + b
print(return_sum(1, 2))
3
def print_sum(a, b):
print(a + b)
print_sum(1, 2)
3
# Notice: these both do the same thing in the end, but in different ways.
# (3) function decomposition: breaking larger problems down in a collection of smaller functions
# Example: write a function that takes a string and returns the number of vowels in the string.
# Step 1: write a function that takes a string and returns True if the string is a vowel, False otherwise.
def is_vowel(char):
if char == "a" or char == "e" or char == "i" or char == "o" or char == "u":
return True
else:
return False
# Step 2: write a function that takes a string and returns the number of vowels in the string.
def count_vowels(s):
num_vowels = 0
for char in s:
if is_vowel(char):
num_vowels += 1
return num_vowels
# Step 3: test your function
print(count_vowels("hello"))
2
# We've learned how to specify the arguments that a function should take:
def greet(name, greeting):
print(greeting + " to you, " + name + "!")
greet("Alex", "Hello")
Hello to you, Alex!
# In cases where you use the same argument value over and over, it can get annoying to type each time.
greet("Daniel", "Hello")
greet("Heather", "Hello")
greet("Tony", "Hello")
greet("Jelani", "Selam")
Hello to you, Daniel! Hello to you, Heather! Hello to you, Tony! Selam to you, Jelani!
# Python allows us to specify a _default value_ for an argument.
# If the caller doesn't specify a value for that argument, the default value is used instead.
def greet(name, greeting="Hello"):
print(greeting + " to you, " + name + "!")
greet("Alex")
greet("Heather")
greet("Tony")
# If the caller specifies a value for that argument, the default value is ignored.
greet("Jelani", "Selam")
Hello to you, Alex! Hello to you, Heather! Hello to you, Tony! Selam to you, Jelani!