Python Foundations, Session 2: Lists, Dictionaries, and Flow Control¶
Instructor: Wesley Beckner
Contact: wesleybeckner@gmail.com
Recording: Video (59 min)
special thanks to David Beck for their contribution to this material
In this session, we will review basic variables and introduce lists and dictionaries as new variable types, or data structures. We will close with seeing conditional execution and functions. Hang on for the ride!
Normally, a notebook begins with import
statements that import packages or libraries that do a lot of heavy lifting for us. We'll get to that later.
2.0 A quick review from last session¶
Recall, we discussed variables and comments.
2.0.1 A quick review of variables¶
Variables are human names we give data objects in our code. Variables in Python should be named using appropriate descriptions of their purpose. By convention, most variable names are lower case
and may optionally contain the underscore character ('_
'). So far, you've only seen examples of functions and variables in Python, but eventually you will encounter all the types of python objects in this table!
Type | Naming Convention | Examples |
---|---|---|
Function | Use a lowercase word or words. Separate words by underscores to improve readability. | function, my_function |
Variable | Use a lowercase single letter, word, or words. Separate words with underscores to improve readability. | x, var, my_variable |
Constant | Use an uppercase single letter, word or words. Separate words with underscores to improve readability. | CONSTANT, MY_CONSTANT, MY_LONG_CONSTANT |
Method | Use a lowercase word or words. Separate words with underscores to improve readability. | class_method, method |
Class | Start each word with a capital letter. Do not separate words with underscores. This style is called camel case. | Model, MyClass |
Module | Use a short, lowercase word or words. Separate words with underscores to improve readability. | module.py, my_module.py |
Package | Use a short, lowercase word or words. Do not separate words with underscores. | package, mypackage |
Some names you might want to use are off-limits because they are reserved words, meaning they are words in Python that have special meaning.
Examples of reserved words that you should not use as variable names are in the table below. The ones in bold are ones we will use in the session today. Remember, these can't be used as variable names!
import | True | False | if | else | def | in |
not | and | or | None | from | continue | pass |
class | await | raise | del | lambda | return | elif |
with | as | finally | nonlocal | while | assert | except |
global | yield | break | try | global |
Let's see an example of a decimal point containing number, known to computers as a floating point number. Let's use \(\pi\) as the number. (Pro tip: you can write equations in Markdown. See this reference.)
pickles = 3.14
print(pickles)
pickles = 3.14
print(pickles)
3.14
Cool. We defined a variable named pickles containing a poor estimate of \(\pi\). Now every place the word pickles
appears, it will have the value 3.14
, at least until we change it.
🏋️ Exercise 1: Picking variable names¶
Is pickles
a good variable name for the value \(\pi\)? If not, what would be a better name? Is it in the reserved word list above? Use the code
cell below to create a new variable with your preferred name in it.
# Cell for Exercise 1
Variables can change their value in Python so we can change the value of pickles
to something else. For example, a definition of what pickles are.
pickles = "A cucumber preserved in vinegar or brine."
print(pickles)
pickles = "A cucumber preserved in vinegar or brine."
print(pickles)
A cucumber preserved in vinegar or brine.
2.0.2 A quick review of comments¶
Just like we should use good naming conventions for variables so they make sense, we should have good comments to help readers follow our code. Good comments can turn a speck of coding gold into a valuable nugget of knowledge. Bad or wrong comments are bugs. If you want to learn more about why we call computer coding problems bugs, read about Grace Hopper and see her photo of a bug
in her notebook.
To comment out some text, use the #
or hashtag or sometimes called the pound character.
# This is an example comment. Notice it is in english and full sentences. That is good style.
# This is an example comment. Notice it is in english and full sentences. That is good style.
2.1 Data Structures: Variables that organize data¶
Many variables you will encounter are more than the above simple data types (integers, strings, floating point numbers). In fact, they may contain a few to many pieces of data rolled into one thing or data structure. Next, we'll discuss two important data structures: lists and dictionaries. There are many advanced data structures in Python that behave like lists and dictionaries, in different settings but their concepts are often similar. Thus, understanding them here will help us understand more advanced concepts. Let's start with the venerable list.
2.1.1 Lists¶
For more than just shopping. A list is an ordered collection of data. By collection, we mean that it contains multiple data. By ordered, we mean that the data are arranged so that they appear first to last like words in a sentence. The order is important for the meaning of the sentence.
Let's begin by creating a list variable named my_list
that contains three pieces of information.
my_list = ['I', 'like', 'pie']
my_list
my_list = ['I', 'like', 'pie']
my_list
['I', 'like', 'pie']
Now the value of the variable my_list
points to a list of three strings. The use of [
, ]
, and ,
are used to denote the begining, end and separator of the list. Like a sentence, this list of words is ordered. I like pie.
Notice, we didn't use a print()
on the variable. The last variable expression in a cell is shown in the notebook by default.
The elements in a list have indices. That is, to access an element in the list, you can refer to it by its index. Think of a list like a very simple table.
index | value |
---|---|
0 | 'I' |
1 | 'like' |
2 | 'pie' |
People might start counting at 1
, but computers start counting at 0
. The first element in a list has the index 0
, the last element in a list has the index of the length of the list minus 1. For our list which is three elements long, the first index will be 0 and the last index will be 2
.
Some programming languages also start counting at 1. These include Fortran, Matlab, and the abominable R. This is unfortunate. Be extra careful if you try to port code from those languages to Python.
If you want to access a list element you can use its index. The index value is designated by appending [
and ]
to the variable name with the index between. Examples are always easier than words:
my_list[0]
Given what you know... What will this output?
my_list[0]
'I'
If you try to use an index that is larger than the length of the list minus 1, you will get an error. Try it!
The different colors means you made a boo boo!
my_list[3]
# my_list[3]
The last line of the error report is the most informative for us now. It should read:
IndexError: list index out of range
It is trying to tell you that an IndexError
occured because the the index you tried to access is out of the range of 0
to 2
, inclusive. Translation: stay in your lane, programmer!
In addition to being able to recall or access a value of a list by the element's index in the list, we can change the value of the element. We will also use the [
<index>
]
notation but like when we set the value of a variable, we will use the =
character. Let's do it!
my_list[2] = 'cake'
my_list
my_list[2] = 'cake'
my_list
['I', 'like', 'cake']
2.1.1.1 Append, and other list functions¶
Finally, let's talk about empty lists and appending items to a list. An empty list is created by setting a variable to []
. This means the variable's data type is a list, but it contains no elements.
a_new_list = []
a_new_list = []
We can append items to a list by using the .append()
function. We'll talk more about functions later, but when this function or method is used on a variable whose data type is list, it will append the value in between the ()
to the end of the list.
a_new_list.append("1st element")
print(a_new_list)
a_new_list.append("2nd element")
print(a_new_list)
a_new_list.append("1st element")
print(a_new_list)
a_new_list.append("2nd element")
print(a_new_list)
['1st element']
['1st element', '2nd element']
Finally, in addition to the .append()
function, there are a lot of functions (or methods) available for lists. See a complete list of them here.
One more we'll touch on quickly is the len()
function. It returns the length of a list. Here is an example:
len(a_new_list)
Before you run this cell. What do you think it will output?
len(a_new_list)
2
2.1.1.2 Slicing¶
Sometimes you want to make a list from consecutive elements of a list. This is called slicing where you cut up a list and get just the consecutive values you want. Slicing is done with the :
character in the index area between the [
and the ]
. Here is an example to pull just the last two items out of my_list
. We use the first index, then a :
, then the last index plus 1. Like this:
my_list[1:3]
You might be asking... WHY +1?? This is because with slices or ranges in Python are known as half-open intervals where the lower bound is inclusive and the upper bound is the non-inclusive limit. TL;DR: add one to the upper end of a slice or a range in Python.
my_list[1:3]
my_list[1:3]
['like', 'cake']
Just for giggles, try it with my_list[1:2]
. You will see the range of the slice is only 1
. That's because 2 - 1 = 1
.
my_list[1:2]
my_list[1:2]
['like']
You don't even need to use the upper bound if all you really mean is the end of the list. For that, you can leave the index empty. Hot dog! Let's see an example...
my_list[1:]
my_list[1:]
['like', 'cake']
But wait, there's more! You can set multiple elements of a list at the same time by slicing. Dig this!
my_list[1:] = ['love', 'puppies']
my_list
my_list[1:] = ['love', 'puppies']
my_list
['I', 'love', 'puppies']
And who doesn't love puppies? Recap... Lists are ordered collections of information that you can recognize by their use of [
and ]
. To access or address elements in the list, you can use indices. They start at 0
in Python. The last element of a list has the index of the length of the list minus 1. When slicing a list, use two indices separated by :
. If you leave one off, it means everything up to or beyond that element.
🙋 Question 1: Slicing¶
Will either one of the following codes will return an error?
my_list[:len(my_list)]
my_list[len(my_list)]
2.1.1.3 Negative indices?!?!¶
A brief note for folks who want to learn more. You can use negative index numbers to access from the end of the list towards the front. That is, a negative 1 (-1
) is the last element in the list. A negative 2 (-2
) is the second to last. The same rules apply for slicing with the :
character.
A quick demo example... Let's get last element in the list using negative indexing. That will be -1
. Here goes...
my_list[-1]
my_list[-1]
'puppies'
We can also use slicing with negative indices. Remember, that slicing works the same way with negative indices, i.e. the the upper bound is non-inclusive. Here is an example using upper and lower bounds. Were you surprised by the results?
my_list[-3:-1]
my_list[-3:-1]
['I', 'love']
2.1.1.4 Lists can contain most anything¶
So far, we've seen a list containing some strings. That made our sentence analogy about the ordering of objects or strings in a list make sense. But lists can contain a mixture of data types and data structures. As a quick example, let's make a list that contains a integer, a string and a floating point number. This will be a four element list.
zoo = [ 42, 'Elephants', 'ate', 3.14 ]
zoo = [ 42, 'Elephants', 'ate', 3.14 ]
zoo
[42, 'Elephants', 'ate', 3.14]
We can even make a list of lists. META!
list_of_lists = [
[ 42, 43, 44, 44 ],
[ 'a', 'b', 'c', 'd' ]
]
list_of_lists[0]
list_of_lists[0][1]
a_list = list_of_lists[0]
a_list[1]
list_of_lists = [
[ 42, 43, 44, 45 ],
[ 'a', 'b', 'c', 'd' ]
]
The important thing here is to have the right number of [
and ]
to embed a list in a list separated between ,
. Yeah, this is super meta.
list_of_lists[0]
[42, 43, 44, 45]
list_of_lists[0][1]
43
list_of_lists[1][1]
'b'
a_list = list_of_lists[0]
a_list[1]
43
🏋️ Exercise 2: accessing lists of lists¶
Make sure you understand why the above works. Take a minute and play with the first and last indices.
- access
45
in list_of_lists - access
d
in list_of_lists
# Cell for exercise 2
2.1.2 Dictionaries¶
For more than just reading on a Friday night.
Sometimes we want to access elements in a data structure by something other than an index. Consider a dictionary on the internet. You look up the word on a seach engine and go to the web page of the entry for the word. Python has a similar concept where the index for an element in a collection is not a number, as it is in a list above, but a key
that, may be a string like 'pickles'
.
2.1.2.1 Key, value pairs¶
In the case of a Python dictionary, we call the definition a value and the way we look up the definition is a key. This results in key and value pairs. One key maps to one value. In our analogy of a internet dictionary, this is the same as the word to definition pairs.
Let's create a simple dictionary with a definition we have alread seen in the tutorials... Pickles.
my_dict = {} # create an empty dictionary
my_dict['pickles'] = "A cucumber preserved in vinegar or brine."
my_dict
my_dict = {} # create an empty dictionary
my_dict['pickles'] = "A cucumber preserved in vinegar or brine."
my_dict
{'pickles': 'A cucumber preserved in vinegar or brine.'}
Notice the use of the #
comment. Nice. Unlike the list, for dictionaries, some of their operations use the {
and }
brackets. Using a key to access or retrieve a value from the dictionary still uses the [
and ]
brackets. Stick with it, for realz.
Case matters in a dictionary because the key
is a data type itself.
my_dict['Pickles']
returns an error (KeyError: 'Pickles'
) and the following does not
my_dict['pickles']
# my_dict['Pickles']
This is a lot like the IndexError
from the list case.
Moving on... You can change the value of a dictionary key by reassigning it. For example below, we use the same key 'pickles'
to change the definition of the word in our dictionary. Notice we still use the [
and ]
brackets but we use the key instead of the index like we did with lists. The change we made in the string is that the cucumbers in pickles are usually small.
my_dict['pickles'] = "A small cucumber preserved in vinegar or brine."
my_dict['pickles'] = "A small cucumber preserved in vinegar or brine."
my_dict
{'pickles': 'A small cucumber preserved in vinegar or brine.'}
Let's add two key
and value
pairs to our dictionary which are in the table below:
key | value |
---|---|
list | An ordered collection. |
dictionary | A collection with unique indices. |
Something like:
my_dict['list'] = "An ordered collection"
print(my_dict)
Is probably where we want to begin.
my_dict['list'] = "An ordered collection"
my_dict
{'list': 'An ordered collection',
'pickles': 'A small cucumber preserved in vinegar or brine.'}
# my_dict[0]
Finally, like the list's .append()
function, there are a lot of functions (or methods) and attributes available for dictionaries. See a complete list of them here.
(we will cover the difference between a method and an attribute more concretely later on...)
2.2 Flow control: If this, then that...¶
Flow control is a fancy phrase meaning to execute some code statements under certain conditions. The simplest case, is an if
statement (figure right below): If a variable is True
then do something. If it is False
then do something else, or do nothing at all.
Flow control figure
In the above figure:
- the
selection
refers toif
statements Iteration
refers to loops or repeating some statements over and over while changing a small number of variable valuesSequence
roughly corresponds to blocks of statements in functions.
Flow control refers how to programs do loops, conditional execution, and order of functional operations. Let's start with conditionals, or the venerable if
statement.
2.2.1 If¶
Let's write a simple if statement
if 5 == 5.0:
print(True)
True
Mathematically, the float 5.0 and integer 5, do evaluate to be the same! What do we notice about the second line? That's right, there's an indentation. Colab and most IDEs will automatically indent for you. Let's practice that below.
2.2.1.1 Indentations in python¶
🏋️ Exercise 3: Writing an if statement¶
practice writing a simple if statement, notice the automatic indentation
# cell for exercise 3.1
2.2.1.2 Conditional fall through and reserved words¶
If statements can be used to execute some lines or block of code if a particular condition is satisfied. E.g. Let's print something based on the entries in the list.
mission = ["let's", "explore", "some", "data", "!"]
if '!' in mission:
print('#notaword')
mission = ["let's", "explore", "some", "data", "!"]
if '!' in mission:
print('#notaword')
#notaword
2.2.1.2.1 in
¶
Notice the use the special reserved word in. This returns the value True
when a value appears in a list and False
when it does not. Notice how it reads like English. Readability is a key feature of Python and is part of the language design philosophy.
Usually we want conditional logic on both sides of a binary condition, e.g. some action when True
and some when False
if '!' in mission:
print("This isn't a full word!")
else:
print("Nothing to see here")
if '!' in mission:
print("This isn't a full word!")
else:
print("Nothing to see here")
This isn't a full word!
2.2.1.2.2 pass
¶
There is a special do nothing word: pass
that skips over some arm of a conditional, e.g.
if 'data' in mission:
print("Congrats, you're working with data, it will be grand!")
else:
pass
if 'data' in mission:
print("Congrats, you're working with data, it will be grand!")
else:
pass
Congrats, you're working with data, it will be grand!
The use of pass
here is very important. While you can actually skip the else
and pass
statements and the code will behave identically, using them is an important signal that you intended for the negative case to do nothing. Most of the time when pass
is used, it is used as a placeholder for an eventual action/function/loop to be filled in. By using pass, we signal this intention.
As a side note, I personally have felt the pangs of conditional fall through. Had I used the else/pass nomenclature, I would have signalled to myself that at some point in the future, I needed to explicitly account for when a specific execution of the code passes through this condition. Because I was not tabulating this conditional fall through, unbeknownst to me code I had productionized, was in fact not working exactly the way I intended it to.
In short, when you have one side of an if
statement that has no code use an else
and a pass
to be a good citizen. When you are writing code, you should start thinking about reading code and how others will read your code. Remember, the person you will collaborate the most about your code is yourself in 3-6 months.
Note: what have you noticed in this session about quotes? What is the difference between '
and "
?
Another simple example:
if True is False:
print("I'm so confused")
else:
print("Everything is right with the world")
if True is False:
print("I'm so confused")
else:
print("Everything is right with the world")
Everything is right with the world
2.2.1.2.3 if
, elif
, and else
¶
It is always good practice to handle all cases explicity. Conditional fall through is a common source of bugs.
Sometimes we wish to test multiple conditions. Use if
, elif
, and else
.
my_favorite = 'pie'
if my_favorite is 'cake':
print("He likes cake! I'll start making a double chocolate velvet cake right now!")
elif my_favorite is 'pie':
print("He likes pie! I'll start making a cherry pie right now!")
else:
print("He likes " + my_favorite + ". I don't know how to make that.")
my_favorite = 'pie'
if my_favorite is 'cake':
print("He likes cake! I'll start making a double chocolate velvet cake right now!")
elif my_favorite is 'pie':
print("He likes pie! I'll start making a cherry pie right now!")
else:
print("He likes " + my_favorite + ". I don't know how to make that.")
He likes pie! I'll start making a cherry pie right now!
Note: There is a big difference between the above using elif
and this code that uses sequential if
s:
if my_favorite is 'pie':
print("He likes pie! I'll start making a double chocolate velvet pie right now!")
if my_favorite is 'pie':
print("He still likes pie! I'll start making a cherry pie right now!")
else:
print("He likes " + my_favorite + ". I don't know how to make that.")
Before you run the cell, can you describe how these two blocks differ in their outcomes?
if my_favorite is 'pie':
print("He likes pie! I'll start making a double chocolate velvet pie right now!")
if my_favorite is 'pie':
print("He still likes pie! I'll start making a cherry pie right now!")
else:
print("He likes " + my_favorite + ". I don't know how to make that.")
He likes pie! I'll start making a double chocolate velvet pie right now!
He still likes pie! I'll start making a cherry pie right now!
2.2.1.2.4 and
, or
and not
¶
Conditionals can take and
and or
and not
. E.g.
my_favorite = 'pie'
if my_favorite is 'cake' or my_favorite is 'pie':
print(my_favorite + " : I have a recipe for that!")
else:
print("Ew! Who eats that?")
Side note: We haven't mentioned this up until now, in the following cell, we are composing a new string using
+
and feeding this into the print statement:my_favorite + " : I have a recipe for that!"
my_favorite = 'pie'
if my_favorite is 'cake' or my_favorite is 'pie':
print(my_favorite + " : I have a recipe for that!")
else:
print("Ew! Who eats that?")
pie : I have a recipe for that!
🏋️ Exercise 4: Writing conditionals¶
- Write a series of two if statements, that both evaluate as true and print something
- Write an if followed by an elif statement, where only one evaluates as true and prints something
# Cell for exercise 4
2.2.2 For¶
For loops are the standard loop, though while
is also common. For has the general form:
for items in list:
do stuff
2.2.2.1 Iterating through objects¶
For loops and collections like tuples, lists and dictionaries are natural friends. The loop is iterating through an object we call an iterable. tuples, lists, and dictionaries, are all iterables
mission
for item in mission:
print(item)
mission
["let's", 'explore', 'some', 'data', '!']
for item in mission:
print(item)
let's
explore
some
data
!
Note that after the for loop has ended, the item
variable remains defined and contains the last value of the list that was iterated over.
item
'!'
You can combine loops and conditionals:
for item in mission:
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
for item in mission:
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
let's is a word in a sentence!
explore is a word in a sentence!
some is a word in a sentence!
data is a word in a sentence!
! doesn't look like a whole word!
Dictionaries can use the keys
method for iterating.
my_dict.keys()
for key in my_dict.keys():
if len(key) > 4:
print(my_dict[key])
my_dict.keys()
dict_keys(['pickles', 'list'])
for key in my_dict.keys():
if len(key) > 4:
print(my_dict[key])
A small cucumber preserved in vinegar or brine.
Strings are basically a list. Therefore, you can use a for loop to iterate over the characters in a string. Note that c
is a typical variable name for characters in a string. Generally, one letter variable names are not a good thing.
my_string = "caffeine"
for c in my_string:
print(c)
my_string = "caffeine"
for c in my_string:
print(c)
c
a
f
f
e
i
n
e
2.2.2.2 range()
¶
Manually constructing a list of sequential numbers is a total pain. A total pain. So Python has a function called range
that simplifies the creation of lists that contain a sequence. Let's see it in action! Note that if we want a sequence from 0 to 2, inclusive, we call the range
function with a argument of 3
. This is like the upper bound in slicing - it is always 1 plus the maximum value you want in the list.
range(3)
range(3)
range(0, 3)
Wait up, hoss. That result doesn't look like a list! True. However, it acts identically to a list, but works a little different under the hood to save memory. The equivalent hand made list would look like this:
[0, 1, 2]
[0, 1, 2]
[0, 1, 2]
2.2.2.2.1 list
, type cast function¶
We can convert a range
to a list
by using the list
type cast function.
list(range(3))
list(range(3))
[0, 1, 2]
Notice that Python (in the newest versions, e.g. 3+) has an object type that is a range. This saves memory and speeds up calculations vs. an explicit representation of a range as a list - but it can be automagically converted to a list on the fly by Python. To show the contents as a list
we can use the type case like with the tuple above.
Sometimes, in older Python docs, you will see xrange
. This used the range object back in Python 2 and range
returned an actual list. Beware of this!
list(range(3))
[0, 1, 2]
Remember earlier with slicing, the syntax :3
meant [0, 1, 2]
? Well, the same upper bound philosophy applies here.
xs = [0, 1, 2]
for x in xs[0:1]:
if x < 2:
print(x)
else:
pass
xs = [0, 1, 2]
for x in xs[0:1]:
if x < 2:
print(x)
else:
pass
0
Let's use range to acccess our list, mission using list element indexing.
for index in range(5):
item = mission[index]
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
for index in range(5):
item = mission[index]
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
let's is a word in a sentence!
explore is a word in a sentence!
some is a word in a sentence!
data is a word in a sentence!
! doesn't look like a whole word!
This would probably be better written as below. Why is it better to use to use the len()
function than hard code the length of the list?
for index in range(len(mission)):
item = mission[index]
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
for index in range(len(mission)):
item = mission[index]
if item.endswith('!'):
print(item + " doesn't look like a whole word!")
else:
print(item + " is a word in a sentence!")
let's is a word in a sentence!
explore is a word in a sentence!
some is a word in a sentence!
data is a word in a sentence!
! doesn't look like a whole word!
But in all, it isn't very Pythonesque to use indexes like that (unless you have another reason in the loop) and you would opt instead for the instructor in instructors
form.
More often, you are doing something with the numbers that requires them to be integers, e.g. math.
sum = 0
for i in range(10):
sum += i
print(sum)
45
Before we leave the topic of range()
, let's take a quick look at the documentation for it here. Notice, it has another calling semantic than the one have have been using.
We have been using this version:
range(stop)
Where the list will end at stop
minus 1. There is another way the range
function can be called which is to give it an inclusive start
and an exclusive stop
:
range(start, stop)
This returns a list of number that go from start
to stop
minus 1.
Let's look at a quick example:
range(1, 9)
range(1, 9)
range(1, 9)
2.2.2.3 Nested for loops¶
You can put a for loop inside another for loop. This is called nesting. Think of it like the Matryoshka dolls. The example below has a nested loop that counts to four each time the outer loop counts up one. The print
function shows the value of the outside loop iterator i
and the inside loop iterator j
and the product of the two values. Notice how the inside loop runs through 1 to 3 for each value of the outside loop.
We use some string formatting for the print
statement. These are called f-strings because there is an f
before the string. Don't worry too much about the print
function statement here as it isn't the point of this example. Advanced topic: for more on formatting strings, see here.
for i in range(1, 4):
for j in range(1, 4):
print(f'{i} * {j} = {i * j}')
for i in range(1, 4):
for j in range(1, 4):
print(f'{i} * {j} = {i * j}')
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
2.2.2.4 Exiting for loops¶
You can exit a for loop if a condition is met. We'll explore this with reserved words break
and continue
2.2.2.4.1 break
¶
Sometimes, in a for loop, you experience a condition where you want to terminate any further iterations of the loop. The reserved word break
will completely exit a for loop. In this example, we exit the for loop when the iteration variable i
is equal to the integer 4.
for i in range(10):
if i == 4:
break
i
for i in range(10):
if i == 4:
break
i
4
2.2.2.4 continue
¶
Sometimes, in a for loop, you want to skip certain elements. The continue
statement will effectively skip any further statements for that element in a list. Below, we sum the numbers from 0
to 9
and skip the value 5
.
sum = 0
for i in range(10):
if i == 5:
continue
else:
print(i)
sum += i
print("sum is ", sum)
for i in range(6):
if i == 3:
continue
else:
print(i)
0
1
2
4
5
2.2.3 while
¶
In contrast to a for
loop, a while
loop continues to execute while the initiating condition continues to evaluate as True.
a = 0
while a < 10:
a += 5
print("hello!")
a
hello!
hello!
10
You can also use break
and continue
in while
loops
while True:
print("hello!")
break
hello!
🙋 Question 2: While Loops¶
What happens in this cell?
a = 0
while a < 10:
if a == 5:
continue
a += 5
print("hello!")
# a = 0
# while a < 10:
# if a == 5:
# continue
# a += 5
# print("hello!")
# a
2.3 The Zen of Python¶
Finally, let's use end with a philosophy of Python. This is a fun Easter Egg, to see it, import this
:
import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
2.4 References¶
Some links to references from content in this notebook are consolidated here for easy access. Enjoy!
- Using equations in Markdown in Jupyter notebooks
- How numbers are represented in a computer
- Grace Hopper and her photo of a
bug
in her notebook - Programmer culture touchpoint: the word grok
- Converting code from one programming language to another is called Porting
- slices and ranges in Python are known as half-open intervals
- Python documentation for lists
- Negative list indices in Python
- Python documentation for dictionaries
- Python documentation for the
range
function - Third party documentation for
if
statements - Third party documentation for
for
loops - Third party documentation for functions
- The correct name for the "Russian Nesting Doll" is a "Matryoshka doll"
- Formatting strings to include values of variables
- Zen of Python
- Easter Egg