Outline
- Control Flow
- L4-1. Introduction
- L4-2. Conditional Statements
- L4-7. Boolean Expressions for Conditions
- L4-10. For Loops
- L4-13. Quiz: For Loops
- L4-15. Quiz: Match Inputs To Outputs
- L4-16. Building Dictionaries
- L4-17. Iterating Through Dictionaries with For Loops
- L4-20. While Loops
- L4-21. Practice: While Loops
- L4-23. Quiz: While Loops
- L4-25. For Loops vs. While Loops
- L4-26. Check for Understanding: For and While Loops
- L4-28. Break, Continue
- L4-29. Quiz: Break, Continue
- L4-31. Practice: Loops
- L4-33. Zip and Enumerate
- L4-34. Quiz: Zip and Enumerate
- L4-36. List Comprehensions
- L4-37.Quiz: List Comprehensions
- L4-39. Practice Questions
- Vocabulary
- Reference
- Further Reading
- Control flow: the sequence in which your code is run.
- we'll learn about several tools in Python:
- if we have more than two possible cases, we can use eilf
elif
short forelse if
=
: assign operator==
: comparison operator
- Unlike other programming language using braces to enclose block of code
- In python, we use indentation to enclose block of code.
- This indentation conventionally comes in multiples of four spaces.
- It's important to be strict about following this convention.
- The Python Style Guide recommends using 4 spaces to indent, rather than using a tab.
- Whichever you use, be aware that "Python 3 disallows mixing the use of tabs and spaces for indentation."
if 18.5 <= weight / height**2 < 25: # height ** 2 compute first
print("BMI is considered 'normal'")
if is_raining and is_sunny:
print("Is there a rainbow?")
if (not unsubscribed) and (location == "USA" or location == "CAN"):
print("send email")
- For really complicated conditions you might need to combine some
and
s,or
s andnot
s together. - Use parentheses if you need to make the combinations clear.
-
it's useless to use any condition that you know will always evaluate to True or False
# Bad example if True: print("This indented code will always get run.") # Another bad example if is_cold or not is_cold: print("This indented code will always get run.")
-
Logical operators
and
,or
andnot
have specific meanings that aren't quite the same as their meanings in plain English.# Bad example if weather == "snow" or "rain": print("Wear boots!") # Good example if weather == "snow" or weather == "rain": print("Wear boots!")
-
Later we'll discuss what happens when we use non-boolean-type objects in place of booleans.
if "rain": # evaluate result is True print("Wear boots!") # Wear boots!
-
This comparison isn’t necessary, since the boolean variable itself is a boolean expression.
# Bad example if is_cold == True: print("The weather is cold!") # Good example, discard unnecessary words if is_cold: print("The weather is cold!")
-
If you want to check whether a boolean is False, you can use the
not
operator.# Bad example if is_hot == False: print("The weather is cold!") # Good example, use "not" operator if not is_hot: print("The weather is cold!")
- By default, the truth value of an object in Python is considered True unless specified as False in the documentation.
-
Here are most of the built-in objects that are considered False in Python:
- constants defined to be false:
None
andFalse
- zero of any numeric type:
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
- empty sequences and collections:
'""
,()
,[]
,{}
,set()
,range(0)
- constants defined to be false:
-
example:
errors = 3 if errors: print("You have {} errors to fix!".format(errors)) else: print("No errors to fix!") # Output: You have 3 errors to fix!
- A
for
loop is used to "iterate", or do something repeatedly, over an iterable. - An iterable is an object that can return one of its elements at a time.
- This can include sequence types, such as strings, lists, and tuples, as well as non-sequence types, such as dictionaries and files.
- common pattern: the name of list cities is the plural form of city
cities = ['new york city', 'mountain view', 'chicago', 'los angeles']
for city in cities:
print(city.title())
print("Done!")
'''
output:
New York City
Mountain View
Chicago
Los Angeles
Done!
'''
range()
is a built-in function used to create an iterable sequence of numbers.range(start=0, stop, step=1)
print(range(4)) # range(0, 4)
print(list(range(4))) # [0, 1, 2, 3]
print(list(range(2, 6))) # [2, 3, 4, 5]
print(list(range(1, 10, 2))) # [1, 3, 5, 7, 9]
- we adopt range in a list before printing it, because printing just the output of range only shows you a range object
-
we can create a list by appending to a new list at each iteration
# Creating a new list cities = ['new york city', 'mountain view', 'chicago', 'los angeles'] capitalized_cities = [] for city in cities: capitalized_cities.append(city.title())
-
Modifying a list is a bit more involved, and requires the use of the
range()
function.-
don't forget to add
range()
cities = ['new york city', 'mountain view', 'chicago', 'los angeles'] for index in range(len(cities)): cities[index] = cities[index].title()
-
names = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]
usernames = []
# write your for loop here
for name in names:
newName = name.replace(" ", "_").lower()
usernames.append(newName)
print(usernames)
'''
output:
['joey_tribbiani', 'monica_geller', 'chandler_bing', 'phoebe_buffay']
'''
- Q2: Let's say instead of creating a new list, we want to modify the names list itself with the changes and write the following code. What would this do?
names = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]
for name in names:
name = name.lower().replace(" ", "_")
print(names)
answer | option | reason |
---|---|---|
Modifies the names list so that each name is lowercase and separated by underscores |
||
(X) | Causes a runtime error | |
(O) | The printed output for the names list will look exactly like it did in the first line |
It doesn't modify the contents of the names list at all. To modify the list you must operate on the list itself, using range , as you saw earlier. |
Deletes the list |
Write a for
loop that iterates over a list of strings, tokens
, and counts how many of them are XML tags. XML is a data language similar to HTML. You can tell if a string is an XML tag if it begins with a left angle bracket "<" and ends with a right angle bracket ">". Keep track of the number of tags using the variable count
.
You can assume that the list of strings will not contain empty strings.
tokens = ['<greeting>', 'Hello World!', '</greeting>']
count = 0
# write your for loop here
for token in tokens:
if (token.startswith('<') and token.endswith('>')):
count += 1
print(count) # 2
-
if we don't want to use
str.startswith()
andstr.endswith()
method, we can use the method 2.method 1: if (token.startswith('<') and token.endswith('>')): method 2: if token[0] == '<' and token[-1] == '>':
range()
from zero to negative number contains nothing
print(list(range(0, -5))) # []
print(list(range(0, -5, 1))) # []
print(list(range(0, -5, -1))) # [0, -1, -2, -3, -4]
- we have the same
book_title
andword_counter
in two methods
book_title = ['great', 'expectations','the', 'adventures', 'of', 'sherlock','holmes','the','great','gasby','hamlet','adventures','of','huckleberry','fin']
word_counter = {}
for word in book_title:
if word in word_counter:
word_counter[word] += 1
else:
word_counter[word] = 1
print(word_counter)
'''
output:
{'great': 2, 'holmes': 1, 'hamlet': 1, 'huckleberry': 1, 'sherlock': 1, 'adventures': 2, 'gasby': 1, 'expectations': 1, 'fin': 1, 'the': 2, 'of': 2}
'''
word_counter.get(word, 0)
: when there's no word inword_counter
, the default value is 0
for word in book_title:
word_counter[word] = word_counter.get(word, 0) + 1
print(word_counter)
'''
output:
{'great': 2, 'holmes': 1, 'hamlet': 1, 'huckleberry': 1, 'sherlock': 1, 'adventures': 2, 'gasby': 1, 'expectations': 1, 'fin': 1, 'the': 2, 'of': 2}
'''
- the dictionary
cast
contains these keys and values
cast = {
"Jerry Seinfeld": "Jerry Seinfeld",
"Julia Louis-Dreyfus": "Elaine Benes",
"Jason Alexander": "George Costanza",
"Michael Richards": "Cosmo Kramer"
}
- Iterating through it in the usual way with a
for
loop would give you just the keys
for key in cast:
print(key)
'''
output:
Jerry Seinfeld
Julia Louis-Dreyfus
Jason Alexander
Michael Richards
'''
- If we wish to iterate through both keys and values, we can use the built-in method
items
like this:
for key, value in cast.items():
print("Actor: {} Role: {}".format(key, value))
'''
output:
Actor: Jerry Seinfeld Role: Jerry Seinfeld
Actor: Julia Louis-Dreyfus Role: Elaine Benes
Actor: Jason Alexander Role: George Costanza
Actor: Michael Richards Role: Cosmo Kramer
'''
items
is an awesome method that returns tuples of key, value pairs
print(cast.items())
'''
output:
dict_items([('Jerry Seinfeld', 'Jerry Seinfeld'), ('Julia Louis-Dreyfus', 'Elaine Benes'), ('Jason Alexander', 'George Costanza'), ('Michael Richards', 'Cosmo Kramer')])
'''
For
loops are an example of "definite iteration" meaning that the loop's body is run a predefined number of times.- "indefinite iteration" which is when a loop repeats an unknown number of times and ends when some condition is met, which is what happens in a
while
loop.
card_deck = [4, 11, 8, 5, 13, 2, 8, 10]
hand = []
# adds the last element of the card_deck list to the hand list
# until the values in hand add up to 17 or more
while sum(hand) < 17:
hand.append(card_deck.pop())
print(sum(hand))
print(hand)
'''
output:
10
18
[10, 8]
'''
- The indented body of the loop should modify at least one variable in the test condition.
- If the value of the test condition never changes, the result is an infinite loop!
# number to find the factorial of
number = 6
# start with our product equal to one
product = 1
# track the current number being multiplied
current = 1
# write your while loop here
while (current <= number):
# multiply the product so far by the current number
product *= current
# increment current with each iteration until it reaches number
current += 1
# print the factorial of number
print(product) # 720
# number to find the factorial of
number = 6
# start with our product equal to one
product = 1
# write your for loop here
# for i in range(1, number): # (X) exit at number 6-1
# for i in range(1, number+1): # (△) exit at number 6
for i in range(2, number+1): # (O) there's no need to mutiple by 1
product *= i
# print the factorial of number
print(product) # 720
Write a while
loop that finds the largest square number less than an integer limit
and stores it in a variable nearest_square
. A square number is the product of an integer multiplied by itself, for example 36 is a square number because it equals 6*6.
For example, if limit
is 40, your code should set the nearest_square
to 36.
-
my answer:
limit = 40 # write your while loop here root = 1 nearest_square = 0 square = root**2 while (square < limit): nearest_square = square root += 1 square = root**2 print(nearest_square)
-
solution:
limit = 40 num = 0 # start from 0 while (num+1)**2 < limit: # +1 is the key point num += 1 nearest_square = num**2 print(nearest_square)
-
for
loops are ideal when the number of iterations is known or finite.# when we # have an iterable collection (list, string, set, tuple, dictionary) for name in names: # when we want to # iterate through a loop for a definite number of times, using range() for i in range(5):
-
while
loops are ideal when the iterations need to continue until a condition is met.# when we want to # use comparison operators while count <= 100: # when you want to # loop based on receiving specific user input. while user_input == 'y':
-
we need to make sure the while loop has:
- a condition expression that will be assessed and when met, will allow you to exit the loop
- make sure the loop is advancing
- the value of the condition variables is changing with each iteration of the loop.
-
Q1: There are certain requirements you want to consider adding into a
while
loop. Which of these requirements must be met? (Select all that apply)answer option reason (O) The condition for exiting the while loop should be included (O) Check if the iteration condition is met (O) Body of the loop should change the value of condition variables -
Q2: Question: What type of loop should we use?
You need to write a loop that takes the numbers in a given list named num_list:
num_list = [422, 136, 524, 85, 96, 719, 85, 92, 10, 17, 312, 542, 87, 23, 86, 191, 116, 35, 173, 45, 149, 59, 84, 69, 113, 166]
Your code should add up the odd numbers in the list, but only up to the first 5 odd numbers together. If there are more than 5 odd numbers, you should stop at the fifth. If there are fewer than 5 odd numbers, add all of the odd numbers.
-
method 1: for loop
num_list = [422, 136, 524, 85, 96, 719, 85, 92, 10, 17, 312, 542, 87, 23, 86, 191, 116, 35, 173, 45, 149, 59, 84, 69, 113, 166] odd_list = [] result_list = [] for num in num_list: if num % 2 == 1: odd_list.append(num) result_list = odd_list[:5] print(result_list)
-
method 2: while loop
num_list = [422, 136, 524, 85, 96, 719, 85, 92, 10, 17, 312, 542, 87, 23, 86, 191, 116, 35, 173, 45, 149, 59, 84, 69, 113, 166] odd_count = 0 index = 0 result_list = [] while ((odd_count < 5) and (index < len(num_list))): if num_list[index] % 2 == 1: result_list.append(num_list[index]) odd_count += 1 index += 1 print(result_list) # [85, 719, 85, 17, 87]
Sometimes we need more control over when a loop should end, or skip an iteration. In these cases, we use the break
and continue
keywords, which can be used in both for
and while
loops.
break
terminates a loopcontinue
skips one iteration of a loop
manifest = [("bananas", 15), ("mattresses", 24), ("dog kennels", 42), ("machine", 120), ("cheeses", 5)]
# the code breaks the loop when weight exceeds or reaches the limit
print("my solution")
weight = 0
items = []
for cargo_name, cargo_weight in manifest:
if weight >= 100: # don't forget equal to
print(" the cargo is full")
break
elif cargo_weight + weight > 100:
print(" skipping: {}".format(cargo_name))
continue
else:
print(" adding: {}".format(cargo_name))
weight += cargo_weight
items.append(cargo_name)
print("\nFinal Weight: {}".format(weight))
print("Final Items: {}".format(items))
'''
output:
my solution
adding: bananas
adding: mattresses
adding: dog kennels
skipping: machine
adding: cheeses
Final Weight: 86
Final Items: ['bananas', 'mattresses', 'dog kennels', 'cheeses']
'''
Write a loop with a break
statement to create a string, news_ticker
, that is exactly 140 characters long. You should create the news ticker by adding headlines from the headlines
list, inserting a space in between each headline. If necessary, truncate the last headline in the middle so that news_ticker
is exactly 140 characters long.
Remember that break
works in both for
and while
loops. Use whichever loop seems most appropriate. Consider adding print
statements to your code to help you resolve bugs.
-
my solution:
-
make sure the length of
news_ticker
never more than 140# HINT: modify the headlines list to verify your loop works with different inputs headlines = ["Local Bear Eaten by Man", "Legislature Announces New Laws", "Peasant Discovers Violence Inherent in System", "Cat Rescues Fireman Stuck in Tree", "Brave Knight Runs Away", "Papperbok Review: Totally Triffic"] news_ticker = "" # write your loop here for headline in headlines: if (len(news_ticker) == 140): break elif (len(news_ticker) + len(headline) >= 140): news_ticker += headline[:140-len(news_ticker)] break else: news_ticker += headline + " " print(news_ticker) print(len(news_ticker)) ''' output: Local Bear Eaten by Man Legislature Announces New Laws Peasant Discovers Violence Inherent in System Cat Rescues Fireman Stuck in Tree Brave 140 '''
-
-
answer:
-
concatenate first, then truncate it
headlines = ["Local Bear Eaten by Man", "Legislature Announces New Laws", "Peasant Discovers Violence Inherent in System", "Cat Rescues Fireman Stuck in Tree", "Brave Knight Runs Away", "Papperbok Review: Totally Triffic"] news_ticker = "" for headline in headlines: news_ticker += headline + " " if len(news_ticker) >= 140: news_ticker = news_ticker[:140] break print(news_ticker) print(len(news_ticker)) ''' output: Local Bear Eaten by Man Legislature Announces New Laws Peasant Discovers Violence Inherent in System Cat Rescues Fireman Stuck in Tree Brave 140 '''
-
Prime numbers are whole numbers that have only two factors: 1 and the number itself. The first few prime numbers are 2, 3, 5, 7.
For instance, 6 has four factors: 1, 2, 3, 6.
1 X 6 = 6
2 X 3 = 6
So we know 6 is not a prime number.
In the following coding environment, write code to check if the numbers provided in the list check_prime
are prime numbers.
-
If the numbers are prime, the code should print "[number] is a prime number."
-
If the number is NOT a prime number, it should print "[number] is not a prime number", and a factor of that number, other than 1 and the number itself: "[factor] is a factor of [number]".
-
Example output:
7 IS a prime number 26 is NOT a prime number, because 2 is a factor of 26
-
my solution:
-
the optimal range is from 2 to
sqrt(number)
or2 <= x <= sqrt(number)
-
number**(1/2)
meanssqrt(number)
-
int()
: cut the number after decimal point(not round off)print(int(1.6)) # 1 print(int(-1.6)) # -1
-
if
number
is 11,int(number**(1/2))
is 3, thus we have to add 1## Your code should check if each number in the list is a prime number check_prime = [26, 39, 51, 53, 57, 79, 85] ## write your code here ## HINT: You can use the modulo operator to find a factor for number in check_prime: for i in range(2, int(number**(1/2)) + 1): if (number%i == 0): factor = i print("{} is NOT a prime number, because {} is a factor of {}".format(number, factor, number)) break else: # we can use for...else clause to reduce the use of flags print("{} IS a prime number".format(number)) ''' output: 26 is NOT a prime number, because 2 is a factor of 26 39 is NOT a prime number, because 3 is a factor of 39 51 is NOT a prime number, because 3 is a factor of 51 53 IS a prime number 57 is NOT a prime number, because 3 is a factor of 57 79 IS a prime number 85 is NOT a prime number, because 5 is a factor of 85 '''
-
-
purpose: reduce the use of unnecessary flag
-
before:
nums = [60, 70, 30, 110, 90] found = False # the flag that can remove for n in nums: if n > 100: found = True # the flag that can remove print("There is a number bigger than 100") break if not found: # the expression that can remove print("Not found!")
-
after:
nums = [60, 70, 30, 110, 90] for n in nums: if n > 100: print("There is a number bigger than 100") break else: print("Not found!")
zip
andenumerate
are useful built-in functions that can come in handy when dealing with loops.
-
zip
returns an iterator that combines multiple iterables into one sequence of tuples. -
Each tuple contains the elements in that position from all the iterables.
print(zip(['a', 'b', 'c'], [1, 2, 3])) # <zip object at 0x10b8a9dc8> print(*zip(['a', 'b', 'c'], [1, 2, 3])) # ('a', 1) ('b', 2) ('c', 3) print(list(zip(['a', 'b', 'c'], [1, 2, 3]))) # [('a', 1), ('b', 2), ('c', 3)]
- Like we did for
range()
we need to convert it to a list or iterate through it with a loop to see the elements.
- Like we did for
-
we could unpack each tuple in a
for
loopletters = ['a', 'b', 'c'] nums = [1, 2, 3] for letter, num in zip(letters, nums): print("{}: {}".format(letter, num)) ''' output: a: 1 b: 2 c: 3 '''
-
In addition to zipping two lists together, you can also unzip a list into tuples using an asterisk.
some_list = [('a', 1), ('b', 2), ('c', 3)] letters, nums = zip(*some_list) print(letters) # ('a', 'b', 'c') print(nums) # (1, 2, 3)
enumerate
is a built in function that returns an iterator of tuples containing indices and values of a list.- We'll often use this when you want the index along with each element of an iterable in a loop.
-
without enumerate:
letters = ['a', 'b', 'c', 'd', 'e'] for i, letter in zip(range(len(letters)), letters): print(i, letter)
-
with enumerate:
letters = ['a', 'b', 'c', 'd', 'e'] for i, letter in enumerate(letters): print(i, letter) ''' output: 0 a 1 b 2 c 3 d 4 e '''
Use zip
to write a for loop that creates a string specifying the label and coordinates of each point and appends it to the list points
. Each string should be formatted as label: x, y
, z. For example, the string for the first coordinate should be F: 23, 677, 4
.
- In the example below,
label, x, y, z
equals to*point
-
the tuple was unpacked using
*
in the format method. This can help making code cleaner!x_coord = [23, 53, 2, -12, 95, 103, 14, -5] y_coord = [677, 233, 405, 433, 905, 376, 432, 445] z_coord = [4, 16, -6, -42, 3, -6, 23, -1] labels = ["F", "J", "A", "Q", "Y", "B", "W", "X"] points = [] # write your for loop here for point in zip(labels, x_coord, y_coord, z_coord): # label, x, y, z = point # points.append("{}: {}, {}, {}".format(label, x, y, z)) points.append("{}: {}, {}, {}".format(*point)) for point in points: print(point) ''' output: F: 23, 677, 4 J: 53, 233, 16 A: 2, 405, -6 Q: -12, 433, -42 Y: 95, 905, 3 B: 103, 376, -6 W: 14, 432, 23 X: -5, 445, -1 '''
-
Use zip
to create a dictionary cast
that uses names
as keys and heights
as values.
-
my solution:
cast_names = ["Barney", "Robin", "Ted", "Lily", "Marshall"] cast_heights = [72, 68, 72, 66, 76] cast = dict() for cast_name, cast_height in zip(cast_names, cast_heights): cast[cast_name] = cast_height print(cast) ''' output: {'Barney': 72, 'Robin': 68, 'Ted': 72, 'Lily': 66, 'Marshall': 76} '''
-
answer:
cast_names = ["Barney", "Robin", "Ted", "Lily", "Marshall"] cast_heights = [72, 68, 72, 66, 76] cast = dict(zip(cast_names, cast_heights)) print(cast) ''' output: {'Barney': 72, 'Robin': 68, 'Ted': 72, 'Lily': 66, 'Marshall': 76} '''
-
The order of elements in this output may vary since dictionaries are unordered.
Use zip
to transpose data
from a 4-by-3 matrix to a 3-by-4 matrix. There's actually a cool trick for this! Feel free to look at the solutions if you can't figure it out.
-
my solution:
data = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)) data_transpose = tuple() # for a, b, c, d in zip(data[0], data[1], data[2], data[3]): # data_transpose += (a, b, c, d,) for x in zip(*data): data_transpose += (x, ) print(data_transpose) ''' output: ((0, 3, 6, 9), (1, 4, 7, 10), (2, 5, 8, 11)) '''
-
answer:
data = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)) data_transpose = tuple(zip(*data)) print(data_transpose) ''' output: ((0, 3, 6, 9), (1, 4, 7, 10), (2, 5, 8, 11)) '''
Use enumerate
to modify the cast
list so that each element contains the name followed by the character's corresponding height. For example, the first element of cast
should change from "Barney Stinson"
to "Barney Stinson 72"
.
cast = ["Barney Stinson", "Robin Scherbatsky", "Ted Mosby", "Lily Aldrin", "Marshall Eriksen"]
heights = [72, 68, 72, 66, 76]
# write your for loop here
for index, name in enumerate(cast):
cast[index] = "{} {}".format(name, heights[index])
print(cast)
'''
output:
['Barney Stinson 72', 'Robin Scherbatsky 68', 'Ted Mosby 72', 'Lily Aldrin 66', 'Marshall Eriksen 76']
'''
-
if we don't want to use
.format()
method, we can use+=
operator alternatively, but remember to convert the type tostr
-
wrong:
# hide cast and heights variable for index, name in enumerate(cast): cast[index] += name + " " + heights[index] # TypeError: Can't convert 'int' object to str implicitly print(cast)
-
right:
# hide cast and heights variable for index, name in enumerate(cast): cast[index] += name + " " + str(heights[index]) print(cast)
-
In the example below, we have the same variables
x_coord
,y_coord
,labels
andpoints
x_coord = [23, 53] y_coord = [677, 233] labels = ["F", "J"] points = []
-
the type of point IS
<class 'tuple'>
-
point = (labels[0], x_coord[0], y_coord[0])
for point in zip(labels, x_coord, y_coord): print(point) ''' output: ('F', 23, 677) ('J', 53, 233) '''
-
the asterisk(
*
) here is used for unpacking the tuplepoint
-
the type of *point is NOT
<class 'tuple'>
-
*point = labels[0], x_coord[0], y_coord[0]
for point in zip(labels, x_coord, y_coord): print(*point) ''' output: F 23 677 J 53 233 '''
for point in zip(labels, x_coord, y_coord):
print("{}: {} x {}".format(*point))
'''
output:
F: 23 x 677
J: 53 x 233
'''
- In Python, we can create lists really quickly and concisely with list comprehensions.
- list comprehensions allow us to create a list using a
for
loop in one step. - list comprehensions are not found in other languages, but are very common in Python
-
without list comprehensions:
cities = ['new york city', 'mountain view', 'chicago', 'los angeles'] capitalized_cities = [] for city in cities: capitalized_cities.append(city.title())
-
with list comprehensions:
cities = ['new york city', 'mountain view', 'chicago', 'los angeles'] capitalized_cities = [city.title() for city in cities] print(capitalized_cities) # ['New York City', 'Mountain View', 'Chicago', 'Los Angeles']
-
another example without list comprehensions:
squares = [] for x in range(9): squares.append(x**2)
-
another example with list comprehensions:
squares = [x**2 for x in range(9)] # [0, 1, 4, 9, 16, 25, 36, 49, 64]
-
we can also add conditionals to list comprehensions
-
add conditionals before
]
squares = [x**2 for x in range(9) if x%2 == 0] # [0, 4, 16, 36, 64]
-
-
if we want to add an
else
, we will get an syntax error like this:squares = [x**2 for x in range(9) if x%2 == 0 else x+3] # SyntaxError: invalid syntax
-
we have to move the conditionals at the beginning of the list comprehensions, right after the expression (
x**2
):squares = [x**2 if x%2 == 0 else x+3 for x in range(9)] # [0, 4, 4, 6, 16, 8, 36, 10, 64]
Use a list comprehension to create a new list first_names
containing just the first names
in names in lowercase.
- don't forget to add
[0]
names = ["Rick Sanchez", "Morty Smith", "Summer Smith", "Jerry Smith", "Beth Smith"]
first_names = [name.lower().split(" ")[0] for name in names]
print(first_names)
'''
output:
['rick', 'morty', 'summer', 'jerry', 'beth']
'''
Use a list comprehension to create a list multiples_3
containing the first 20 multiples of 3.
-
my solution:
multiples_3 = [x for x in range(1, 61, 1) if x%3 == 0] print(multiples_3) ''' output: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60] '''
-
answer:
multiples_3 = [x * 3 for x in range(1, 21)] print(multiples_3) ''' output: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60] '''
Use a list comprehension to create a list of names passed
that only include those that scored at least 65.
- don't forget to use
.items()
method when usefor...in
loop in dictionaries
scores = {
"Rick Sanchez": 70,
"Morty Smith": 35,
"Summer Smith": 82,
"Jerry Smith": 23,
"Beth Smith": 98
}
passed = [name for name, score in scores.items() if score >= 65]
print(passed)
- we have the same variable
nominated
,winners
:
click here to see the variables
nominated = {1931: ['Norman Taurog', 'Wesley Ruggles', 'Clarence Brown', 'Lewis Milestone', 'Josef Von Sternberg'], 1932: ['Frank Borzage', 'King Vidor', 'Josef Von Sternberg'], 1933: ['Frank Lloyd', 'Frank Capra', 'George Cukor'], 1934: ['Frank Capra', 'Victor Schertzinger', 'W. S. Van Dyke'], 1935: ['John Ford', 'Michael Curtiz', 'Henry Hathaway', 'Frank Lloyd'], 1936: ['Frank Capra', 'William Wyler', 'Robert Z. Leonard', 'Gregory La Cava', 'W. S. Van Dyke'], 1937: ['Leo McCarey', 'Sidney Franklin', 'William Dieterle', 'Gregory La Cava', 'William Wellman'], 1938: ['Frank Capra', 'Michael Curtiz', 'Norman Taurog', 'King Vidor', 'Michael Curtiz'], 1939: ['Sam Wood', 'Frank Capra', 'John Ford', 'William Wyler', 'Victor Fleming'], 1940: ['John Ford', 'Sam Wood', 'William Wyler', 'George Cukor', 'Alfred Hitchcock'], 1941: ['John Ford', 'Orson Welles', 'Alexander Hall', 'William Wyler', 'Howard Hawks'], 1942: ['Sam Wood', 'Mervyn LeRoy', 'John Farrow', 'Michael Curtiz', 'William Wyler'], 1943: ['Michael Curtiz', 'Ernst Lubitsch', 'Clarence Brown', 'George Stevens', 'Henry King'], 1944: ['Leo McCarey', 'Billy Wilder', 'Otto Preminger', 'Alfred Hitchcock', 'Henry King'], 1945: ['Billy Wilder', 'Leo McCarey', 'Clarence Brown', 'Jean Renoir', 'Alfred Hitchcock'], 1946: ['David Lean', 'Frank Capra', 'Robert Siodmak', 'Clarence Brown', 'William Wyler'], 1947: ['Elia Kazan', 'Henry Koster', 'Edward Dmytryk', 'George Cukor', 'David Lean'], 1948: ['John Huston', 'Laurence Olivier', 'Jean Negulesco', 'Fred Zinnemann', 'Anatole Litvak'], 1949: ['Joseph L. Mankiewicz', 'Robert Rossen', 'William A. Wellman', 'Carol Reed', 'William Wyler'], 1950: ['Joseph L. Mankiewicz', 'John Huston', 'George Cukor', 'Billy Wilder', 'Carol Reed'], 1951: ['George Stevens', 'John Huston', 'Vincente Minnelli', 'William Wyler', 'Elia Kazan'], 1952: ['John Ford', 'Joseph L. Mankiewicz', 'Cecil B. DeMille', 'Fred Zinnemann', 'John Huston'], 1953: ['Fred Zinnemann', 'Charles Walters', 'William Wyler', 'George Stevens', 'Billy Wilder'], 1954: ['Elia Kazan', 'George Seaton', 'William Wellman', 'Alfred Hitchcock', 'Billy Wilder'], 1955: ['Delbert Mann', 'John Sturges', 'Elia Kazan', 'Joshua Logan', 'David Lean'], 1956: ['George Stevens', 'Michael Anderson', 'William Wyler', 'Walter Lang', 'King Vidor'], 1957: ['David Lean', 'Mark Robson', 'Joshua Logan', 'Sidney Lumet', 'Billy Wilder'], 1958: ['Richard Brooks', 'Stanley Kramer', 'Robert Wise', 'Mark Robson', 'Vincente Minnelli'], 1959: ['George Stevens', 'Fred Zinnemann', 'Jack Clayton', 'Billy Wilder', 'William Wyler'], 1960: ['Billy Wilder', 'Jules Dassin', 'Alfred Hitchcock', 'Jack Cardiff', 'Fred Zinnemann'], 1961: ['J. Lee Thompson', 'Robert Rossen', 'Stanley Kramer', 'Federico Fellini', 'Robert Wise', 'Jerome Robbins'], 1962: ['David Lean', 'Frank Perry', 'Pietro Germi', 'Arthur Penn', 'Robert Mulligan'], 1963: ['Elia Kazan', 'Otto Preminger', 'Federico Fellini', 'Martin Ritt', 'Tony Richardson'], 1964: ['George Cukor', 'Peter Glenville', 'Stanley Kubrick', 'Robert Stevenson', 'Michael Cacoyannis'], 1965: ['William Wyler', 'John Schlesinger', 'David Lean', 'Hiroshi Teshigahara', 'Robert Wise'], 1966: ['Fred Zinnemann', 'Michelangelo Antonioni', 'Claude Lelouch', 'Richard Brooks', 'Mike Nichols'], 1967: ['Arthur Penn', 'Stanley Kramer', 'Richard Brooks', 'Norman Jewison', 'Mike Nichols'], 1968: ['Carol Reed', 'Gillo Pontecorvo', 'Anthony Harvey', 'Franco Zeffirelli', 'Stanley Kubrick'], 1969: ['John Schlesinger', 'Arthur Penn', 'George Roy Hill', 'Sydney Pollack', 'Costa-Gavras'], 1970: ['Franklin J. Schaffner', 'Federico Fellini', 'Arthur Hiller', 'Robert Altman', 'Ken Russell'], 1971: ['Stanley Kubrick', 'Norman Jewison', 'Peter Bogdanovich', 'John Schlesinger', 'William Friedkin'], 1972: ['Bob Fosse', 'John Boorman', 'Jan Troell', 'Francis Ford Coppola', 'Joseph L. Mankiewicz'], 1973: ['George Roy Hill', 'George Lucas', 'Ingmar Bergman', 'William Friedkin', 'Bernardo Bertolucci'], 1974: ['Francis Ford Coppola', 'Roman Polanski', 'Francois Truffaut', 'Bob Fosse', 'John Cassavetes'], 1975: ['Federico Fellini', 'Stanley Kubrick', 'Sidney Lumet', 'Robert Altman', 'Milos Forman'], 1976: ['Alan J. Pakula', 'Ingmar Bergman', 'Sidney Lumet', 'Lina Wertmuller', 'John G. Avildsen'], 1977: ['Steven Spielberg', 'Fred Zinnemann', 'George Lucas', 'Herbert Ross', 'Woody Allen'], 1978: ['Hal Ashby', 'Warren Beatty', 'Buck Henry', 'Woody Allen', 'Alan Parker', 'Michael Cimino'], 1979: ['Bob Fosse', 'Francis Coppola', 'Peter Yates', 'Edouard Molinaro', 'Robert Benton'], 1980: ['David Lynch', 'Martin Scorsese', 'Richard Rush', 'Roman Polanski', 'Robert Redford'], 1981: ['Louis Malle', 'Hugh Hudson', 'Mark Rydell', 'Steven Spielberg', 'Warren Beatty'], 1982: ['Wolfgang Petersen', 'Steven Spielberg', 'Sydney Pollack', 'Sidney Lumet', 'Richard Attenborough'], 1983: ['Peter Yates', 'Ingmar Bergman', 'Mike Nichols', 'Bruce Beresford', 'James L. Brooks'], 1984: ['Woody Allen', 'Roland Joffe', 'David Lean', 'Robert Benton', 'Milos Forman'], 1985: ['Hector Babenco', 'John Huston', 'Akira Kurosawa', 'Peter Weir', 'Sydney Pollack'], 1986: ['David Lynch', 'Woody Allen', 'Roland Joffe', 'James Ivory', 'Oliver Stone'], 1987: ['Bernardo Bertolucci', 'Adrian Lyne', 'John Boorman', 'Norman Jewison', 'Lasse Hallstrom'], 1988: ['Barry Levinson', 'Charles Crichton', 'Martin Scorsese', 'Alan Parker', 'Mike Nichols'], 1989: ['Woody Allen', 'Peter Weir', 'Kenneth Branagh', 'Jim Sheridan', 'Oliver Stone'], 1990: ['Francis Ford Coppola', 'Martin Scorsese', 'Stephen Frears', 'Barbet Schroeder', 'Kevin Costner'], 1991: ['John Singleton', 'Barry Levinson', 'Oliver Stone', 'Ridley Scott', 'Jonathan Demme'], 1992: ['Clint Eastwood', 'Neil Jordan', 'James Ivory', 'Robert Altman', 'Martin Brest'], 1993: ['Jim Sheridan', 'Jane Campion', 'James Ivory', 'Robert Altman', 'Steven Spielberg'], 1994: ['Woody Allen', 'Quentin Tarantino', 'Robert Redford', 'Krzysztof Kieslowski', 'Robert Zemeckis'], 1995: ['Chris Noonan', 'Tim Robbins', 'Mike Figgis', 'Michael Radford', 'Mel Gibson'], 1996: ['Anthony Minghella', 'Joel Coen', 'Milos Forman', 'Mike Leigh', 'Scott Hicks'], 1997: ['Peter Cattaneo', 'Gus Van Sant', 'Curtis Hanson', 'Atom Egoyan', 'James Cameron'], 1998: ['Roberto Benigni', 'John Madden', 'Terrence Malick', 'Peter Weir', 'Steven Spielberg'], 1999: ['Spike Jonze', 'Lasse Hallstrom', 'Michael Mann', 'M. Night Shyamalan', 'Sam Mendes'], 2000: ['Stephen Daldry', 'Ang Lee', 'Steven Soderbergh', 'Ridley Scott', 'Steven Soderbergh'], 2001: ['Ridley Scott', 'Robert Altman', 'Peter Jackson', 'David Lynch', 'Ron Howard'], 2002: ['Rob Marshall', 'Martin Scorsese', 'Stephen Daldry', 'Pedro Almodovar', 'Roman Polanski'], 2003: ['Fernando Meirelles', 'Sofia Coppola', 'Peter Weir', 'Clint Eastwood', 'Peter Jackson'], 2004: ['Martin Scorsese', 'Taylor Hackford', 'Alexander Payne', 'Mike Leigh', 'Clint Eastwood'], 2005: ['Ang Lee', 'Bennett Miller', 'Paul Haggis', 'George Clooney', 'Steven Spielberg'], 2006: ['Alejandro Gonzaalez Inarritu', 'Clint Eastwood', 'Stephen Frears', 'Paul Greengrass', 'Martin Scorsese'], 2007: ['Julian Schnabel', 'Jason Reitman', 'Tony Gilroy', 'Paul Thomas Anderson', 'Joel Coen', 'Ethan Coen'], 2008: ['David Fincher', 'Ron Howard', 'Gus Van Sant', 'Stephen Daldry', 'Danny Boyle'], 2009: ['James Cameron', 'Quentin Tarantino', 'Lee Daniels', 'Jason Reitman', 'Kathryn Bigelow'], 2010: ['Darren Aronofsky', 'David O. Russell', 'David Fincher', 'Ethan Coen', 'Joel Coen', 'Tom Hooper']}
winners = {1931: ['Norman Taurog'], 1932: ['Frank Borzage'], 1933: ['Frank Lloyd'], 1934: ['Frank Capra'], 1935: ['John Ford'], 1936: ['Frank Capra'], 1937: ['Leo McCarey'], 1938: ['Frank Capra'], 1939: ['Victor Fleming'], 1940: ['John Ford'], 1941: ['John Ford'], 1942: ['William Wyler'], 1943: ['Michael Curtiz'], 1944: ['Leo McCarey'], 1945: ['Billy Wilder'], 1946: ['William Wyler'], 1947: ['Elia Kazan'], 1948: ['John Huston'], 1949: ['Joseph L. Mankiewicz'], 1950: ['Joseph L. Mankiewicz'], 1951: ['George Stevens'], 1952: ['John Ford'], 1953: ['Fred Zinnemann'], 1954: ['Elia Kazan'], 1955: ['Delbert Mann'], 1956: ['George Stevens'], 1957: ['David Lean'], 1958: ['Vincente Minnelli'], 1959: ['William Wyler'], 1960: ['Billy Wilder'], 1961: ['Jerome Robbins', 'Robert Wise'], 1962: ['David Lean'], 1963: ['Tony Richardson'], 1964: ['George Cukor'], 1965: ['Robert Wise'], 1966: ['Fred Zinnemann'], 1967: ['Mike Nichols'], 1968: ['Carol Reed'], 1969: ['John Schlesinger'], 1970: ['Franklin J. Schaffner'], 1971: ['William Friedkin'], 1972: ['Bob Fosse'], 1973: ['George Roy Hill'], 1974: ['Francis Ford Coppola'], 1975: ['Milos Forman'], 1976: ['John G. Avildsen'], 1977: ['Woody Allen'], 1978: ['Michael Cimino'], 1979: ['Robert Benton'], 1980: ['Robert Redford'], 1981: ['Warren Beatty'], 1982: ['Richard Attenborough'], 1983: ['James L. Brooks'], 1984: ['Milos Forman'], 1985: ['Sydney Pollack'], 1986: ['Oliver Stone'], 1987: ['Bernardo Bertolucci'], 1988: ['Barry Levinson'], 1989: ['Oliver Stone'], 1990: ['Kevin Costner'], 1991: ['Jonathan Demme'], 1992: ['Clint Eastwood'], 1993: ['Steven Spielberg'], 1994: ['Robert Zemeckis'], 1995: ['Mel Gibson'], 1996: ['Anthony Minghella'], 1997: ['James Cameron'], 1998: ['Steven Spielberg'], 1999: ['Sam Mendes'], 2000: ['Steven Soderbergh'], 2001: ['Ron Howard'], 2002: ['Roman Polanski'], 2003: ['Peter Jackson'], 2004: ['Clint Eastwood'], 2005: ['Ang Lee'], 2006: ['Martin Scorsese'], 2007: ['Ethan Coen', 'Joel Coen'], 2008: ['Danny Boyle'], 2009: ['Kathryn Bigelow'], 2010: ['Tom Hooper']}
-
1A. Create a dictionary that includes the count of Oscar nominations for each director in the nominations list
### 1A: Create dictionary with the count of Oscar nominations for each director nom_count_dict = {} for directors in nominated.values(): for director in directors: if not nom_count_dict.get(director, None): nom_count_dict[director] = 1 else: nom_count_dict[director] += 1 print("nom_count_dict = {}\n".format(nom_count_dict))
-
1B. Provide a dictionary with the count of Oscar wins for each director in the winners list.
- warning: there's not only one winner a year sometimes
1961: ['Jerome Robbins', 'Robert Wise']
-
method 1: use the same approach as Q1A:
-
instead of using
.items
retrive both keys and values, we can use.keys()
or.values()
method alternatively### 1B: Create dictionary with the count of Oscar wins for each director win_count_dict = {} for winner_list in winners.values(): for winner in winner_list: # there's not only one winner a year sometimes if not win_count_dict.get(winner, None): win_count_dict[winner] = 1 else: win_count_dict[winner] += 1 print("win_count_dict = {}".format(win_count_dict))
-
-
method 2: if the directors aren't in the
win_count_dict
,get
return 0 for the director- before
if not win_count_dict.get(winner, None): win_count_dict[winner] = 1 else: win_count_dict[winner] += 1
- after
win_count_dict[winner] = win_count_dict.get(winner, 0) + 1
Provide a list with the name(s) of the director(s) with the most Oscar wins. We are asking for a list because there could be more than 1 director tied for the most Oscar wins.
-
the
winners
dictionary is same as above, I don't mention it again -
first shot:
### For Question 2: Please provide a list with the name(s) of the director(s) with ### the most Oscar wins. The list can hold the names of multiple directors, ### since there can be more than 1 director tied with the most Oscar wins. most_win_director = [] # Add your code here win_count_dict = {} for winner_list in winners.values(): for winner in winner_list: win_count_dict[winner] = win_count_dict.get(winner, 0) + 1 win_name = [name for name in win_count_dict.keys()] win_count = [count for count in win_count_dict.values()] most_win_index = [index for index, count in enumerate(win_count) if count == max(win_count)] most_win_director = [win_name[index] for index in most_win_index] print("most_win_director = {}".format(most_win_director)) ''' output: most_win_director = ['John Ford'] '''
-
second shot:
-
most_win_index
can be wrote shorter-
before
win_name = [name for name in win_count_dict.keys()] win_count = [count for count in win_count_dict.values()] most_win_index = [index for index, count in enumerate(win_count) if count == max(win_count)]
-
after(if there's more than 1 most_win_index, the code below will only show the first match index)most_win_index = max(win_count_dict.values())
-
-
we don't need an
win_name
list to store all the winners. Just using list comprehensions instead.-
before
win_name = [name for name in win_count_dict.keys()] most_win_director = [win_name[index] for index in most_win_index]
-
after
most_win_director = [name for name, count in win_count_dict.items() if count == most_win_index]
-
-
full code:
most_win_director = [] # Add your code here win_count_dict = {} for winner_list in winners.values(): for winner in winner_list: win_count_dict[winner] = win_count_dict.get(winner, 0) + 1 # most_win_index = max(win_count_dict.values()) most_win_index = [index for index, count in enumerate(win_count) if count == max(win_count)] most_win_director = [name for name, count in win_count_dict.items() if count == most_win_index] print("most_win_director = {}".format(most_win_director)) ''' output: most_win_director = ['John Ford'] '''
-
- pay-as-you-go(PAYG) (n.) 現收現付
- concession ticket (n.) 優惠票
- succinct (adj.) 簡潔的
- blackjack dealer (n.) 賭場發牌手
- manifest (n.) 載貨單
- hummus (n.) 鷹嘴豆泥
- kennel (n.) 狗舍
- start off (phr.) 出發