CS50 INTRODUCTION TO PYTHON PARTS 1 NOTES
CS50 INTRODUCTION TO PYTHON PARTS 1 NOTES
cs50.harvard.edu/python/2022/notes/0
Final Project
Gallery of Final Projects
Shorts
Status Page
License
Lecture 0
1/15
VS Code is a special type of text editor that is called a compiler. At the top, you’ll
notice a text editor. At the bottom, you will see a terminal where you can execute
commands.
In the terminal, you can execute code hello.py to start coding.
In the text editor above, you can type print("hello, world"). This is a famous
canonical program that nearly all coders write during their learning process.
In the terminal window, you can execute commands. To run this program, you are
going to need to move your cursor to the bottom of the screen, clicking in the terminal
window. You can now type a second command in the terminal window. Next to the
dollar sign, type python hello.py and press the enter key on your keyboard.
Recall that computers really only understand zeros and ones. Therefore, when you
run python hello.py, python will interpret the text that you created in hello.py and
translate it into the zeros and ones that the computer can understand.
The result of running the python hello.py program is hello, world.
Congrats! You just created your first program.
Functions
Functions are verbs or actions that the computer or computer language will already
know how to perform.
In your hello.py program, the print function knows how to print to the terminal
window.
The print function takes arguments. In this case, "hello, world" are the arguments
that the print function takes.
Bugs
Bugs are a natural part of coding. These are mistakes, problems for you to solve!
Don’t get discouraged! This is part of the process of becoming a great programmer.
Imagine in our hello.py program that accidentally typed print("hello, world"
notice that we missed the final ) required by the compiler. If I purposefully make this
mistake, you’ll the compiler will output an error in the terminal window!
Often, the error messages will inform you of your mistakes and provide you clues on
how to fix them. However, there will be many times when the compiler is not this kind.
2/15
This edit alone, however, will not allow your program to output what your user inputs.
For that, we will need to introduce you to variables
Variables
Notice that this equal = sign in the middle of name = input("What's your name? ")
has a special role in programming. This equal sign literally assigns what is on the right
to what is on the left. Therefore, the value returned by input("What's your name?
") is assigned to name.
The program will return hello, name in the terminal window regardless of what the
user types.
Further editing our code, you could type
Comments
Comments are a way for programmers to track what they are doing in their programs
and even inform others about their intentions for a block of code. In short, they are
notes for yourself and others who will see your code!
3/15
You can add comments to your program to be able to see what it is that your program
is doing. You might edit your code as follows:
Pseudocode
# Print hello
print("hello,")
The output in the terminal, if we typed “David” we would be hello, David. Success.
4/15
Rewinding a bit in our code back to the following, there was a visual side effect of
having the result appear on multiple lines:
By providing end="" we are overwriting the default value of end such that it never
creates a new line after this first print statement. Providing the name as “David”, the
output in the terminal window will be hello, David.
Formatting Strings
5/15
Probably the most elegant way to use strings would be as follows:
More on Strings
You should never expect your user to cooperate as intended. Therefore, you will need
to ensure that the input of your user is corrected or checked.
It turns out that built into strings is the ability to remove whitespace from a string.
By utilizing the method strip on name as name = name.strip(), will strip all the
whitespaces on the left and right of the users input. You can modify your code to be:
Rerunning this program, regardless of how many spaces you type before or after the
name, it will strip off all the whitespace.
Using the title method, it would title case the user’s name:
By this point, you might be very tired of typing python repeatedly in the terminal
window. You cause use the up arrow of your keyboard to recall the most recent
terminal commands you have made.
6/15
Notice that you can modify your code to be more efficient:
# Remove whitespace from the str and capitalize the first letter of each word
name = name.strip().title()
# Ask the user for their name, remove whitespace from the str and capitalize
the first letter of each word
name = input("What's your name? ").strip().title()
Integers or int
In Python, an integer is referred to as an int.
In the world of mathematics, we are familiar with +, -, *, /, and % operators. That last
operator % or modulo operator may not be very familiar to you.
You don’t have to use the text editor window in your compiler to run Python code.
Down in your terminal, you can run python alone. You will be presented with >>> in
the terminal window. You can then run live, interactive code. You could type 1+1, and it
will run that calculation. This mode will not commonly be used during this course.
Opening up VS Code again, we can type code calculator.py in the terminal. This
will create a new file in which we will create our own calculator.
7/15
First, we can declare a few variables.
x = 1
y = 2
z = x + y
print(z)
Naturally, when we run python calculator.py we get the result in the terminal
window of 3. We can make this more interactive using the input function.
x = input("What's x? ")
y = input("What's y? ")
z = x + y
print(z)
Running this program, we discover that the output is incorrect as 12. Why might this
be?
Prior, we have seen how the + sign concatenates two strings. Because your input from
your keyboard on your computer comes into the compiler as text, it is treated as a
string. We, therefore, need to convert this input from a string to an integer. We can do
so as follows:
x = input("What's x? ")
y = input("What's y? ")
z = int(x) + int(y)
print(z)
The result is now correct. The use of int(x) is called “casting,” where a value is
temporarily changed from one type of variable (in this case, a string) to another (here,
an integer).
x = int(input("What's x? "))
y = int(input("What's y? "))
print(x + y)
This illustrates that you can run functions on functions. The inner function is run first,
and then the outer one is run. First, the input function is run. Then, the int function.
8/15
Readability Wins
When deciding on your approach to a coding task, remember that one could make a
reasonable argument for many approaches to the same problem.
Regardless of what approach you take to a programming task, remember that your
code must be readable. You should use comments to give yourself and others clues
about what your code is doing. Further, you should create code in a way that is
readable.
Float Basics
A floating point value is a real number that has a decimal point in it, such as 0.52.
You can change your code to support floats as follows:
x = float(input("What's x? "))
y = float(input("What's y? "))
print(x + y)
This change allows your user to enter 1.2 and 3.4 to present a total of 4.6.
Let’s imagine, however, that you want to round the total to the nearest integer.
Looking at the Python documentation for round, you’ll see that the available
arguments are round(number[n, ndigits]). Those square brackets indicate that
something optional can be specified by the programmer. Therefore, you could do
round(n) to round a digit to its nearest integer. Alternatively, you could code as
follows:
9/15
What if we wanted to format the output of long numbers? For example, rather than
seeing 1000, you may wish to see 1,000. You could modify your code as follows:
Though quite cryptic, that print(f"{z:,}") creates a scenario where the outputted z
will include commas where the result could look like 1,000 or 2,500.
More on Floats
How can we round floating point values? First, modify your code as follows:
Let’s imagine that we want to round this down. We could modify our code as follows:
As we might expect, this will round the result to the nearest two decimal points.
10/15
We could also use fstring to format the output as follows:
This cryptic fstring code displays the same as our prior rounding strategy.
Def
Wouldn’t it be nice to create our own functions?
Let’s bring back our final code of hello.py by typing code hello.py into the terminal
window. Your starting code should look as follows:
# Ask the user for their name, remove whitespace from the str and capitalize
the first letter of each word
name = input("What's your name? ").strip().title()
We can better our code to create our own special function that says “hello” for us!
Erasing all our code in our text editor, let’s start from scratch:
Attempting to run this code, your compiler will throw an error. After all, there is no
defined function for hello.
11/15
We can create our own function called hello as follows:
def hello():
print("hello")
Here, in the first lines, you are creating your hello function. This time, however, you
are telling the compiler that this function takes a single parameter: a variable called
to. Therefore, when you call hello(name) the computer passes name into the hello
function as to. This is how we pass values into functions. Very useful! Running
python hello.py in the terminal window, you’ll see that the output is much closer to
our ideal presented earlier in this lecture.
12/15
We can change our code to add a default value to hello:
Test out your code yourself. Notice how the first hello will behave as you might
expect, and the second hello, which is not passed a value, will, by default, output
hello, world.
We don’t have to have our function at the start of our program. We can move it down,
but we need to tell the compiler that we have a main function and a separate hello
function.
def main():
This alone, however, will create an error of sorts. If we run python hello.py, nothing
happens! The reason for this is that nothing in this code is actually calling the main
function and bringing our program to life.
13/15
The following very small modification will call the main function and restore our
program to working order:
def main():
main()
Returning Values
You can imagine many scenarios where you don’t just want a function to perform an
action but also to return a value back to the main function. For example, rather than
simply printing the calculation of x + y, you may want a function to return the value of
this calculation back to another part of your program. This “passing back” of a value
we call a return value.
Returning to our calculator.py code by typing code calculator.py. Erase all code
there. Rework the code as follows:
def main():
x = int(input("What's x? "))
print("x squared is", square(x))
def square(n):
return n * n
main()
Summing Up
Through the work of this single lecture, you have learned abilities that you will use countless
times in your own programs. You have learned about…
14/15
Creating your first programs in Python;
Functions;
Bugs;
Variables;
Comments;
Pseudocode;
Strings;
Parameters;
Formatted Strings;
Integers;
Principles of readability;
Floats;
Creating your own functions; and
Return values.
15/15
CS50’s Introduction to Programming with Python
cs50.harvard.edu/python/2022/notes/1
Lecture 1
Conditionals
Conditionals allow you, the programmer, to allow your program to make decisions: As
if your program has the choice between taking the left-hand road or the right-hand
road based upon certain conditions.
Built within Python are a set of “operators” that are used to ask mathematical
questions.
> and < symbols are probably quite familiar to you.
>= denotes “greater than or equal to.”
<= denotes “less than or equal to.”
== denotes “equals, though do notice the double equal sign! A single equal sign would
assign a value. Double equal signs are used to compare variables.
!= denotes “not equal to.
Conditional statements compare a left-hand term to a right-hand term.
if Statements
In your terminal window, type code compare.py. This will create a brand new file
called “compare.”
1/14
In the text editor window, begin with the following:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x < y:
print("x is less than y")
Notice how your program takes the input of the user for both x and y, casting them as
integers and saving them into their respective x and y variables. Then, the if
statement compares x and y. If the condition of x < y is met, the print statement is
executed.
if statements use bool or boolean values (true or false) to decide whether or not to
execute. If the statement of x > y is true, the compiler will register it as true and
execute the code.
x = int(input("What's x? "))
y = int(input("What's y? "))
if x < y:
print("x is less than y")
if x > y:
print("x is greater than y")
if x == y:
print("x is equal to y")
Notice how you are providing a series of if statements. First, the first if statement is
evaluated. Then, the second if statement runs its evaluation. Finally, the last if
statement runs its evaluation. This flow of decisions is called “control flow.”
2/14
Our code can be represented as follows:
start
x<
True
x>
True
x ==
True
stop
3/14
This program can be improved by not asking three consecutive questions. After all,
not all three questions can have an outcome of true! Revise your program as follows:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x < y:
print("x is less than y")
elif x > y:
print("x is greater than y")
elif x == y:
print("x is equal to y")
Notice how the use of elif allows the program to make fewer decisions. First, the if
statement is evaluated. If this statement is found to be true, all the elif statements
will not be run at all. However, if the if statement is evaluated and found to be false,
the first elif will be evaluated. If this is true, it will not run the final evaluation.
4/14
Our code can be represented as follows:
start
x<
False
x>
True False
True x ==
True
"x is less than "x is greater than y" "x is equal to y" False
stop
While your computer may not notice a difference speed-wise between our first
program and this revised program, consider how an online server running billions or
trillions of these types of calculations each day could definitely be impacted by such a
small coding decision.
5/14
There is one final improvement we can make to our program. Notice how logically
elif x == y is not a necessary evaluation to run. After all, if logically x is not less
than y AND x is not greater than y, x MUST equal y. Therefore, we don’t have to run
elif x == y. We can create a “catch-all,” default outcome using an else statement.
We can revise as follows:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x < y:
print("x is less than y")
elif x > y:
print("x is greater than y")
else:
print("x is equal to y")
Notice how the relative complexity of this program has decreased through our
revision.
6/14
Our code can be represented as follows:
start
x<
False
True x>
True False
"x is less than "x is greater than y" "x is equal to y"
stop
or
or allows your program to decide between one or more alternatives. For example, we
could further edit our program as follows:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x < y or x > y:
print("x is not equal to y")
else:
print("x is equal to y")
Notice that the result of our program is the same, but the complexity is decreased.
The efficiency of our code is increased.
7/14
At this point, our code is pretty great. However, could the design be further improved?
We could further edit our code as follows:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x != y:
print("x is not equal to y")
else:
print("x is equal to y")
Notice how we removed the or entirely and simply asked, “Is x not equal to y?” We
ask one and only one question. Very efficient!
For the purpose of illustration, we could also change our code as follows:
x = int(input("What's x? "))
y = int(input("What's y? "))
if x == y:
print("x is equal to y")
else:
print("x is not equal to y")
Notice that the == operator evaluates if what is on the left and right are equal to one
another. The use of double equal signs is very important. If you use only one equal
sign, an error will likely be thrown by the compiler.
8/14
Our code can be illustrated as follows:
start
x ==
True False
stop
and
Similar to or, and can be used within conditional statements.
Execute in the terminal window code grade.py. Start your new program as follows:
Notice that by executing python grade.py, you will be able to input a score and get a
grade. However, notice how there is potential for bugs.
9/14
Typically, we do not want to ever trust our users to input the correct information. We
could improve our code as follows:
Notice how Python allows you to chain together the operators and conditions in a way
quite uncommon to other programming languages.
Notice how the program is improved by asking fewer questions. This makes our
program easier to read and far more maintainable in the future.
Modulo
In mathematics, parity refers to whether a number is either even or odd.
The modulo % operator in programming allows one to see if two numbers divide evenly
or divide and have a remainder.
For example, 4 % 2 would result in zero, because it evenly divides. However, 3 % 2
does not divide evenly and would result in a number other than zero!
10/14
In the terminal window, create a new program by typing code parity.py. In the text
editor window, type your code as follows:
x = int(input("What's x? "))
if x % 2 == 0:
print("Even")
else:
print("Odd")
Notice how our users can type in any number 1 or greater to see if it is even or odd.
def main():
x = int(input("What's x? "))
if is_even(x):
print("Even")
else:
print("Odd")
def is_even(n):
if n % 2 == 0:
return True
else:
return False
main()
Notice that our if statement is_even(x) works even though there is no operator
there. This is because our function returns a bool (or boolean), true or false, back to
the main function. The if statement simply evaluates whether or not is_even of x is
true or false.
Pythonic
11/14
In the programming world, there are types of programming that are called “Pythonic”
in nature. That is, there are ways to program that are sometimes only seen in Python
programming. Consider the following revision to our program:
def main():
x = int(input("What's x? "))
if is_even(x):
print("Even")
else:
print("Odd")
def is_even(n):
return True if n % 2 == 0 else False
main()
Notice that this return statement in our code is almost like a sentence in English. This
is a unique way of coding only seen in Python.
We can further revise our code and make it more and more readable:
def main():
x = int(input("What's x? "))
if is_even(x):
print("Even")
else:
print("Odd")
def is_even(n):
return n % 2 == 0
main()
Notice that the program will evaluate what is happening within the n % 2 == 0 as
either true or false and simply return that to the main function.
match
Similar to if, elif, and else statements, match statements can be used to
conditionally run code that matches certain values.
12/14
Consider the following program:
if name == "Harry":
print("Gryffindor")
elif name == "Hermione":
print("Gryffindor")
elif name == "Ron":
print("Gryffindor")
elif name == "Draco":
print("Slytherin")
else:
print("Who?")
Notice the first three conditional statements print the same response.
We can improve this code slightly with the use of the or keyword:
Notice the number of elif statements has decreased, improving the readability of our
code.
Alternatively, we can use match statements to map names to houses. Consider the
following code:
match name:
case "Harry":
print("Gryffindor")
case "Hermione":
print("Gryffindor")
case "Ron":
print("Gryffindor")
case "Draco":
print("Slytherin")
case _:
print("Who?")
Notice the use of the _ symbol in the last case. This will match with any input,
resulting in similar behavior as an else statement.
13/14
A match statement compares the value following the match keyword with each of the
values following the case keywords. In the event a match is found, the respective
indented code section is executed, and the program stops the matching.
We can improve the code:
match name:
case "Harry" | "Hermione" | "Ron":
print("Gryffindor")
case "Draco":
print("Slytherin")
case _:
print("Who?")
Notice, the use of the single vertical bar |. Much like the or keyword, this allows us to
check for multiple values in the same case statement.
Summing Up
You now have the power within Python to use conditional statements to ask questions and
have your program take action accordingly. In this lecture, we discussed…
Conditionals;
if Statements;
Control flow, elif, and else;
or;
and;
Modulo;
Creating your own function;
Pythonic coding;
and match.
14/14
CS50’s Introduction to Programming with Python
cs50.harvard.edu/python/2022/notes/2
Lecture 2
Loops
Essentially, loops are a way to do something over and over again.
Begin by typing code cat.py in the terminal window.
In the text editor, begin with the following code:
print("meow")
print("meow")
print("meow")
Running this code by typing python cat.py, you’ll notice that the program meows
three times.
In developing as a programmer, you want to consider how one could improve areas of
one’s code where one types the same thing over and over again. Imagine where one
might want to “meow” 500 times. Would it be logical to type that same expression of
print("meow") over and over again?
Loops enable you to create a block of code that executes over and over again.
While Loops
The while loop is nearly universal throughout all coding languages.
Such a loop will repeat a block of code over and over again.
In the text editor window, edit your code as follows:
i = 3
while i != 0:
print("meow")
Notice how even though this code will execute print("meow") multiple times, it will
never stop! It will loop forever. while loops work by repeatedly asking if the condition
of the loop has been fulfilled. In this case, the compiler is asking, “does i not equal
zero?” When you get stuck in a loop that executes forever, you can press control-c
on your keyboard to break out of the loop.
1/14
To fix this loop that lasts forever, we can edit our code as follows
i = 3
while i != 0:
print("meow")
i = i - 1
Notice that now our code executes properly, reducing i by 1 for each “iteration”
through the loop. The term iteration has special significance within coding. By
iteration, we mean one cycle through the loop. The first iteration is the “0th” iteration
through the loop. The second is the “1st” iteration. In programming, we count starting
with 0, then 1, then 2.
i = 1
while i <= 3:
print("meow")
i = i + 1
Notice that when we code i = i + 1 we assign the value of i from the right to the
left. Above, we are starting i at one, like most humans count (1, 2, 3). If you execute
the code above, you’ll see it meows three times. It’s best practice in programming to
begin counting with zero.
i = 0
while i < 3:
print("meow")
i += 1
Notice how changing the operator to i < 3 allows our code to function as intended.
We begin by counting with 0 and it iterates through our loop three times, producing
three meows. Also, notice how i += 1 is the same as saying i = i + 1.
2/14
Our code at this point is illustrated as follows:
start
i=0
i<3
True False
"meow" stop
i +=
For Loops
A for loop is a different type of loop.
To best understand a for loop, it’s best to begin by talking about a new variable type
called a list in Python. As in other areas of our lives, we can have a grocery list, a
to-do list, etc.
A for loop iterates through a list of items. For example, in the text editor window,
modify your cat.py code as follows:
Notice how clean this code is compared to your previous while loop code. In this
code, i begins with 0, meows, i is assigned 1, meows, and, finally, i is assigned 2,
meows, and then ends.
3/14
While this code accomplishes what we want, there are some possibilities for
improving our code for extreme cases. At first glance, our code looks great. However,
what if you wanted to iterate up to a million? It’s best to create code that can work with
such extreme cases. Accordingly, we can improve our code as follows:
for i in range(3):
print("meow")
Notice how range(3) provides back three values (0, 1, and 2) automatically. This code
will execute and produce the intended effect, meowing three times.
Our code can be further improved. Notice how we never use i explicitly in our code.
That is, while Python needs the i as a place to store the number of the iteration of the
loop, we never use it for any other purpose. In Python, if such a variable does not
have any other significance in our code, we can simply represent this variable as a
single underscore _. Therefore, you can modify your code as follows:
for _ in range(3):
print("meow")
Notice how changing the i to _ has zero impact on the functioning of our program.
Our code can be further improved. To stretch your mind to the possibilities within
Python, consider the following code:
print("meow" * 3)
Notice how it will meow three times, but the program will produce meowmeowmeow as
the result. Consider: How could you create a line break at the end of each meow?
print("meow\n" * 3, end="")
Notice how this code produces three meows, each on a separate line. By adding
end="" and the \n we tell the compiler to add a line break at the end of each meow.
4/14
For example, let’s try prompting the user for a number greater than or equal 0:
while True:
n = int(input("What's n? "))
if n < 0:
continue
else:
break
Notice that we’ve introduced two new keywords in Python, continue and break.
continue explicitly tells Python to go to the next iteration of a loop. break, on the
other hand, tells Python to “break out” of a loop early before it has finished all of its
iterations. In this case, we’ll continue to the next iteration of the loop when n is less
than 0—ultimately reprompting the user with “What’s n?”. If, though, n is greater than
or equal to 0, we’ll break out of the loop and allow the rest of our program to run.
It turns out that the continue keyword is redundant in this case. We can improve our
code as follows:
while True:
n = int(input("What's n? "))
if n > 0:
break
for _ in range(n):
print("meow")
Notice how this while loop will always run (forever) until n is greater than 0. When n is
greater than 0, the loop breaks.
5/14
Bringing in our prior learning, we can use functions to further improve our code:
def main():
meow(get_number())
def get_number():
while True:
n = int(input("What's n? "))
if n > 1:
return n
def meow(n):
for _ in range(n):
print("meow")
main()
Notice how not only did we change your code to operate in multiple functions, but we
also used a return statement to return the value of n back to the main function.
print(students[0])
print(students[1])
print(students[2])
Notice how we have a list of students with their names as above. We then print the
student who is at the 0th location, “Hermoine”. Each of the other students is printed as
well.
6/14
Just as we illustrated previously, we can use a loop to iterate over the list. You can
improve your code as follows:
Notice that for each student in the students list, it will print the student as intended.
You might wonder why we did not use the _ designation as discussed prior. We
choose not to do this because student is explicitly used in our code.
Length
We can utilize len as a way of checking the length of the list called students.
Imagine that you don’t simply want to print the name of the student but also their
position in the list. To accomplish this, you can edit your code as follows:
for i in range(len(students)):
print(i + 1, students[i])
Notice how executing this code results in not only getting the position of each student
plus one using i + 1, but also prints the name of each student. len allows you to
dynamically see how long the list of the students is regardless of how much it grows.
Dictionaries
dicts or dictionaries is a data structure that allows you to associate keys with values.
Where a list is a list of multiple values, a dict associates a key with a value.
Considering the houses of Hogwarts, we might assign specific students to specific
houses.
7/14
We could use lists alone to accomplish this:
Notice that we can promise that we will always keep these lists in order. The individual
at the first position of students is associated with the house at the first position of the
houses list, and so on. However, this can become quite cumbersome as our lists grow!
students = {
"Hermoine": "Gryffindor",
"Harry": "Gryffindor",
"Ron": "Gryffindor",
"Draco": "Slytherin",
}
print(students["Hermoine"])
print(students["Harry"])
print(students["Ron"])
print(students["Draco"])
Notice how we use {} curly braces to create a dictionary. Where lists use numbers
to iterate through the list, dicts allow us to use words.
$ python hogwarts.py
Gryffindor
Gryffindor
Gryffindor
Slytherin
students = {
"Hermoine": "Gryffindor",
"Harry": "Gryffindor",
"Ron": "Gryffindor",
"Draco": "Slytherin",
}
for student in students:
print(student)
Notice how, executing this code, the for loop will only iterate through all the keys,
resulting in a list of the names of the students. How could we print out both values and
keys?
8/14
Modify your code as follows:
students = {
"Hermoine": "Gryffindor",
"Harry": "Gryffindor",
"Ron": "Gryffindor",
"Draco": "Slytherin",
}
for student in students:
print(student, students[student])
Notice how students[student] will go to each student’s key and find the value of
their house. Execute your code, and you’ll notice how the output is a bit messy.
students = {
"Hermoine": "Gryffindor",
"Harry": "Gryffindor",
"Ron": "Gryffindor",
"Draco": "Slytherin",
}
for student in students:
print(student, students[student], sep=", ")
Notice how this creates a clean separation of a , between each item printed.
$ python hogwarts.py
Hermoine, Gryffindor
Harry, Gryffindor
Ron, Gryffindor
Draco, Slytherin
9/14
What if we have more information about our students? How could we associate more
data with each of the students?
You can imagine wanting to have lots of data associated with multiple keys. Enhance
your code as follows:
students = [
{"name": "Hermoine", "house": "Gryffindor", "patronus": "Otter"},
{"name": "Harry", "house": "Gryffindor", "patronus": "Stag"},
{"name": "Ron", "house": "Gryffindor", "patronus": "Jack Russell terrier"},
{"name": "Draco", "house": "Slytherin", "patronus": None},
]
Notice how this code creates a list of dicts. The list called students has four
dicts within it: One for each student. Also, notice that Python has a special None
designation where there is no value associated with a key.
Now, you have access to a whole host of interesting data about these students. Now,
further modify your code as follows:
students = [
{"name": "Hermoine", "house": "Gryffindor", "patronus": "Otter"},
{"name": "Harry", "house": "Gryffindor", "patronus": "Stag"},
{"name": "Ron", "house": "Gryffindor", "patronus": "Jack Russell terrier"},
{"name": "Draco", "house": "Slytherin", "patronus": None},
]
Notice how the for loop will iterate through each of the dicts inside the list called
students.
10/14
You can learn more in Python’s Documentation of dicts.
Mario
Remember that the classic game Mario has a hero jumping over bricks. Let’s create a
textual representation of this game.
print("#")
print("#")
print("#")
Notice how we are copying and pasting the same code over and over again.
for _ in range(3):
print("#")
11/14
Consider: Could we further abstract for solving more sophisticated problems later with
this code? Modify your code as follows:
def main():
print_column(3)
def print_column(height):
for _ in range(height):
print("#")
main()
Notice how our column can grow as much as we want without any hard coding.
Now, let’s try to print a row horizontally. Modify your code as follows:
def main():
print_row(4)
def print_row(width):
print("?" * width)
main()
Notice how we now have code that can create left-to-right blocks.
Examining the slide below, notice how Mario has both rows and columns of blocks.
12/14
Consider: How could we implement both rows and columns within our code? Modify
your code as follows:
def main():
print_square(3)
def print_square(size):
# Print brick
print("#", end="")
main()
Notice that we have an outer loop that addresses each row in the square. Then, we
have an inner loop that prints a brick in each row. Finally, we have a print statement
that prints a blank line.
def main():
print_square(3)
def print_square(size):
for i in range(size):
print_row(size)
def print_row(width):
print("#" * width)
main()
Summing Up
You now have another power in your growing list of your Python abilities. In this lecture, we
addressed…
13/14
Loops
while
for
len
list
dict
14/14
CS50’s Introduction to Programming with Python
cs50.harvard.edu/python/2022/notes/3/
Final Project
Gallery of Final Projects
Shorts
Status Page
License
2024-01-24 23:54:28
Lecture 3
Exceptions
1/7
Exceptions are things that go wrong within our coding.
In our text editor, type code hello.py to create a new file. Type as follows (with the intentional
errors included):
print("hello, world)
Running python hello.py in our terminal window, an error is outputted. The compiler states that it
is a “syntax error.”” Syntax errors are those that require you to double-check that you typed in your
code correction.
Runtime Errors
Runtime errors refer to those created by unexpected behavior within your code. For example,
perhaps you intended for a user to input a number, but they input a character instead. Your
program may throw an error because of this unexpected input from the user.
In your terminal window, run code number.py. Code as follows in your text editor:
x = int(input("What's x? "))
print(f"x is {x}")
Notice that by including the f, we tell Python to interpolate what is in the curly braces as the value
of x. Further, testing out your code, you can imagine how one could easily type in a string or a
character instead of a number. Even still, a user could type nothing at all – simply hitting the enter
key.
As programmers, we should be defensive to ensure that our users are entering what we expected.
We might consider “corner cases” such as -1, 0, or cat.
If we run this program and type in “cat”, we’ll suddenly see ValueError: invalid literal for
int() with base 10: 'cat' Essentially, the Python interpreter does not like that we passed “cat”
to the print function.
An effective strategy to fix this potential error would be to create “error handling” to ensure the user
behaves as we intend.
try
2/7
In Python try and except are ways of testing out user input before something goes wrong. Modify
your code as follows:
try:
x = int(input("What's x?"))
print(f"x is {x}")
except ValueError:
print("x is not an integer")
Notice how, running this code, inputting 50 will be accepted. However, typing in cat will produce an
error visible to the user, instructing them why their input was not accepted.
This is still not the best way to implement this code. Notice that we are trying to do two lines of
code. For best practice, we should only try the fewest lines of code possible that we are
concerned could fail. Adjust your code as follows:
try:
x = int(input("What's x?"))
except ValueError:
print("x is not an integer")
print(f"x is {x}")
Notice that while this accomplishes our goal of trying as few lines as possible, we now face a new
error! We face a NameError where x is not defined. Look at this code and consider: Why is x
not defined in some cases?
Indeed, if you examine the order of operations in x = int(input("What's x?")), working right to
left, it could take an incorrectly inputted character and attempt to assign it as an integer. If this fails,
the assignment of the value of x never occurs. Therefore, there is no x to print on our final line of
code.
else
It turns out that there is another way to implement try that could catch errors of this nature.
try:
x = int(input("What's x?"))
except ValueError:
print("x is not an integer")
else:
print(f"x is {x}")
Notice that if no exception occurs, it will then run the block of code within else. Running python
number.py and supplying 50, you’ll notice that the result will be printed. Trying again, this time
supplying cat, you’ll notice that the program now catches the error.
3/7
Considering improving our code, notice that we are being a bit rude to our user. If our user does
not cooperate, we currently simply end our program. Consider how we can use a loop to prompt
the user for x and if they don’t prompt again! Improve your code as follows:
while True:
try:
x = int(input("What's x?"))
except ValueError:
print("x is not an integer")
else:
break
print(f"x is {x}")
Notice that while True will loop forever. If the user succeeds in supplying the correct input, we can
break from the loop and then print the output. Now, a user that inputs something incorrectly will be
asked for input again.
def main():
x = get_int()
print(f"x is {x}")
def get_int():
while True:
try:
x = int(input("What's x?"))
except ValueError:
print("x is not an integer")
else:
break
return x
main()
Notice that we are manifesting many great properties. First, we have abstracted away the ability to
get an integer. Now, this whole program boils down to the first three lines of the program.
4/7
Even still, we can improve this program. Consider what else you could do to improve this program.
Modify your code as follows:
def main():
x = get_int()
print(f"x is {x}")
def get_int():
while True:
try:
x = int(input("What's x?"))
except ValueError:
print("x is not an integer")
else:
return x
main()
Notice that return will not only break you out of a loop, but it will also return a value.
def main():
x = get_int()
print(f"x is {x}")
def get_int():
while True:
try:
return int(input("What's x?"))
except ValueError:
print("x is not an integer")
main()
Notice this does the same thing as the previous iteration of our code, simply with fewer lines.
pass
5/7
We can make it such that our code does not warn our user, but simply re-asks them our prompting
question by modifying our code as follows:
def main():
x = get_int()
print(f"x is {x}")
def get_int():
while True:
try:
return int(input("What's x?"))
except ValueError:
pass
main()
Notice that our code will still function but will not repeatedly inform the user of their error. In some
cases, you’ll want to be very clear to the user what error is being produced. Other times, you might
decide that you simply want to ask them for input again.
One final refinement that could improve the implementation of this get_int function. Right now,
notice that we are relying currently upon the honor system that the x is in both the main and
get_int functions. We probably want to pass in a prompt that the user sees when asked for input.
Modify your code as follows.
def main():
x = get_int("What's x? ")
print(f"x is {x}")
def get_int(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
pass
main()
Summing Up
Errors are inevitable in your code. However, you have the opportunity to use what was learned today to
help prevent these errors. In this lecture, you learned about…
Exceptions
Value Errors
6/7
Runtime Errors
try
else
pass
7/7