{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"
\n",
"\n",
"Created by [Nathan Kelber](http://nkelber.com) and Ted Lawless for [JSTOR Labs](https://labs.jstor.org/) under [Creative Commons CC BY License](https://creativecommons.org/licenses/by/4.0/)
\n",
"For questions/comments/improvements, email nathan.kelber@ithaka.org.
\n",
"___"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python Basics 2\n",
"\n",
"**Description:** This lesson describes the basics of [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) including:\n",
"* [Boolean values](https://docs.constellate.org/key-terms/#boolean-value)\n",
"* [Boolean operators](https://docs.constellate.org/key-terms/#boolean-operator)\n",
"* [Comparison operators](https://docs.constellate.org/key-terms/#comparison-operator)\n",
"* `if` statements\n",
"* `else` statements\n",
"* `elif` statements\n",
"* `while` and `for` loop statements\n",
"* Handling errors with `try` and `except`\n",
"\n",
"and the basics of writing functions:\n",
"\n",
"* `def` statements\n",
"* [Local scope](https://docs.constellate.org/key-terms/#local-scope)\n",
"* [Global scope](https://docs.constellate.org/key-terms/#global-scope)\n",
"\n",
"This is part 2 of 3 in the series *Python Basics* that will prepare you to do text analysis using the [Python](https://docs.constellate.org/key-terms/#python) programming language.\n",
"\n",
"**Use Case:** For Learners (Detailed explanation, not ideal for researchers)\n",
"\n",
"**Difficulty:** Beginner\n",
"\n",
"**Completion Time:** 90 minutes\n",
"\n",
"**Knowledge Required:** \n",
"* [Getting Started with Jupyter Notebooks](./getting-started-with-jupyter.ipynb)\n",
"* [Python Basics 1](./python-basics-1.ipynb)\n",
"\n",
"**Knowledge Recommended:** None\n",
"\n",
"**Data Format:** None\n",
"\n",
"**Libraries Used:** `random` to generate random numbers\n",
"\n",
"**Research Pipeline:** None\n",
"___"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[![Python Basics 2 image](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/video/python-basics-2.png)](https://www.youtube.com/watch?v=yzApQqZkJ2c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Flow Control Statements\n",
"\n",
"In *Python Basics 1*, you learned about [expressions](https://docs.constellate.org/key-terms/#expression), [operators](https://docs.constellate.org/key-terms/#operator), [variables](https://docs.constellate.org/key-terms/#variable), and a few native [Python](https://docs.constellate.org/key-terms/#python) [functions](https://docs.constellate.org/key-terms/#). We wrote programs that executed line-by-line, starting at the top and running to the bottom. This approach works great for simple programs that may execute a few tasks, but as you begin writing programs that can do multiple tasks you'll need a way for your programs to decide which action comes next. We can control when (or if) code gets executed with [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement). If a program is a set of steps for accomplishing a task, then [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) help the program decide the next action.\n",
"\n",
"[Flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) work like a flowchart. For example, let's say your goal is to hang out and relax with friends. There are a number of steps you might take, depending on whether your friends are available or you feel like making some new friends.\n",
"\n",
"![Flowchart to hangout with friends](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/friends_flowchart.png)\n",
"\n",
"Each diamond in our flowchart represents a decision that has to be made about the best step to take next. This is the essence of [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement). They help a program decide what the next step should be given the current circumstances."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Boolean Values\n",
"\n",
"One way we to create [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) is with [boolean values](https://docs.constellate.org/key-terms/#boolean-value) that have two possible values: **True** or **False**. In our example above, we could consider a \"Yes\" to be \"True\" and a \"No\" to be \"False.\" When we have the data we need to answer each question, we could store that answer in a variable, like:\n",
"\n",
"* ```are_friends_available = False```\n",
"* ```make_new_friends = True```\n",
"* ```new_friend_available = True```\n",
"\n",
"This would allow us to determine which action to take next. When we assign [boolean values](https://docs.constellate.org/key-terms/#boolean-value) to a [variable](https://docs.constellate.org/key-terms/#variable), the first letter must be capitalized:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Note, the first letter of a boolean value must always be capitalized in Python\n",
"are_friends_available = false\n",
"print(are_friends_available)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The boolean values **True** and **False** cannot be used for variable names. \n",
"# Treating the boolean value True as a variable will create an error\n",
"True = 7"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# But we can store Boolean values in a variable\n",
"\n",
"pizza_is_life = False\n",
"tacos_are_life = True"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Comparison Operators\n",
"Now that we have a way to store [integers](https://docs.constellate.org/key-terms/#integer), [floats](https://docs.constellate.org/key-terms/#float), [strings](https://docs.constellate.org/key-terms/#string), and [boolean values](https://docs.constellate.org/key-terms/#boolean-value) in [variables](https://docs.constellate.org/key-terms/#variable), we can use a [comparison operator](https://docs.constellate.org/key-terms/#comparison-operator) to help make decisions based on those values. We used the [comparison operator](https://docs.constellate.org/key-terms/#comparison-operator) `==` in *Python Basics 1*. This operator asks whether two [expressions](https://docs.constellate.org/key-terms/#expression) are equal to each other."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Comparing two values with the comparison operator ==\n",
"67 == 67"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Note, a comparison operator uses ==\n",
"# Do not confuse with variable assignment statement which uses a single =\n",
"67 = 67"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are additional [comparison operators](https://docs.constellate.org/key-terms/#comparison-operator) that can help us with [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement).\n",
"\n",
"|Operator|Meaning|\n",
"|---|---|\n",
"|==|Equal to|\n",
"|!=|Not equal to|\n",
"|<|Less than|\n",
"|>|Greater than|\n",
"|<=|Less than or equal to|\n",
"|>=|Greater than or equal to|"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [],
"source": [
"# Use the \"Not equal to\" operator\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [],
"source": [
"# Use the \"equal to\" operator with a string\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A string cannot be equal to a float or an integer."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [],
"source": [
"# Try using the \"equal to\" operator to compare a string with an integer\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But an integer can be equal to a float."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [],
"source": [
"# Try using the \"equal to\" operator to compare an integer with a float\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can use the comparison operator with variables."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [],
"source": [
"# Using a comparison operator on a variable\n",
"# Create a variable number_of_dogs and assign the value of zero\n",
"\n",
"\n",
"# Check whether number_of_dogs is greater than or equal to 1\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Boolean Operators (and/or/not)\n",
"We can also use [Boolean operators](https://docs.constellate.org/key-terms/#boolean-operator) (**and**/**or**/**not**) to create [expressions](https://docs.constellate.org/key-terms/#expression) that evaluate to a single [Boolean value](https://docs.constellate.org/key-terms/#boolean-value) (**True**/**False**).\n",
"\n",
"#### Using the Boolean Operator `and`\n",
"The `and` operator determines whether *both* conditions are **True**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# If condition one is True AND condition two is True\n",
"# What will the evaluation be?\n",
"True and True"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# If condition one is True AND condition two is False\n",
"# What will the evaluation be?\n",
"True and False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order for an ```and``` [expression](https://docs.constellate.org/key-terms/#expression) to evaluate to **True**, every condition must be **True**. Here is the \"Truth Table\" for every pair:\n",
"\n",
"|Expression|Evaluation|\n",
"|---|---|\n",
"|True and True|True|\n",
"|True and False|False|\n",
"|False and True|False|\n",
"|False and False|False|\n",
"\n",
"Since `and` [expressions](https://docs.constellate.org/key-terms/#expression) require all conditions to be **True**, they can easily result in **False** evaluations.\n",
"\n",
"#### Using the Boolean Operator ```or```\n",
"The ```or``` operator determines whether *any* condition is **True**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Is expression one True OR is expression two True?\n",
"True or False"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Is condition one True OR is condition two True?\n",
"False or False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An ```or``` [expression](https://docs.constellate.org/key-terms/#expression) evaluates to **True** if *any* condition is **True**. Here is the \"Truth Table\" for every pair:\n",
"\n",
"|Expression|Evaluation|\n",
"|---|---|\n",
"|True or True|True|\n",
"|True or False|True|\n",
"|False or True|True|\n",
"|False or False|False|\n",
"\n",
"Since ```or``` [expressions](https://docs.constellate.org/key-terms/#expression) only require a single condition to be **True**, they can easily result in **True** evaluations.\n",
"\n",
"#### Using the Boolean Operator ```not```\n",
"The```not``` operator only operates on a single expression, essentially flipping **True** to **False** or **False** to **True**. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The not operator flips a True to False\n",
"not False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Combining Boolean and Comparison Operators\n",
"\n",
"We can combine [Boolean operators](https://docs.constellate.org/key-terms/#boolean-operator) and [comparison operators](https://docs.constellate.org/key-terms/#comparison-operator) to create even more nuanced **Truth** tests."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Evaluating two conditions with integers at once\n",
"(3 < 22) and (60 == 34) # What does each condition evaluate to?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Evaluating two conditions with integers at once\n",
"(3 == 45) or (3 != 7) # What does each condition evaluate to?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So far, we have evaluated one or two conditions at once, but we could compare even more at once. (In practice, this is rare since it creates code that can be difficult to read.) [Boolean operators](https://docs.constellate.org/key-terms/#boolean-operator) also have an order of operations like mathematical [operators](https://docs.constellate.org/key-terms/#operator). They resolve in the order of `not`, `and`, then `or`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Writing a Flow Control Statement\n",
"\n",
"The general form of a [flow control statement](https://docs.constellate.org/key-terms/#flow-control-statement) in [Python](https://docs.constellate.org/key-terms/#python) is a condition followed by an action clause:\n",
"\n",
"`In this condition:`
\n",
" `perform this action`\n",
"\n",
"Let's return to part of our flowchart for hanging out with friends.\n",
"\n",
"![Flowchart showing if homework is yes then do assignment](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/do_homework_chart.png)\n",
"\n",
"We can imagine a [flow control statement](https://docs.constellate.org/key-terms/#flow-control-statement) that would look something like:\n",
"\n",
"`if have_homework == True:`
\n",
" `complete assignment`\n",
" \n",
"The condition is given followed by a colon (:). The action clause then follows on the next line, indented into a [code block](https://docs.constellate.org/key-terms/#code-block).\n",
"\n",
"* If the condition is fulfilled (evaluates to **True**), the action clause in the block of code is executed. \n",
"* If the condition is not fulfilled (evaluates to **False**), the action clause in the block of code is skipped over."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Code Blocks\n",
"A [code block](https://docs.constellate.org/key-terms/#code-block) is a snippet of code that begins with an indentation. A [code block](https://docs.constellate.org/key-terms/#code-block) can be a single line or many lines long. Blocks can contain other blocks forming a hierarchal structure. In such a case, the second block is indented an additional degree. Any given block ends when the number of indentations in the current line is less than the number that started the block.\n",
"\n",
"![Visualization of code block indentations](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/code_block_indentation.png)\n",
"\n",
"Since the level of indentation describes which code block will be executed, improper indentations will make your code crash. When using indentations to create code blocks, look carefully to make sure you are working in the code block you intend. Each indentation for a code block is created by pressing the tab key."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Types of Flow Control Statements\n",
"\n",
"The code example above uses an `if` statement, but there are other kinds of [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) available in [Python](https://docs.constellate.org/key-terms/#python).\n",
"\n",
"|Statement|Means|Condition for execution|\n",
"|---|---|---|\n",
"|`if`|if|if the condition is fulfilled|\n",
"|`elif`|else if|if no previous conditions were met *and* this condition is met|\n",
"|`else`|else|if no condition is met (no condition is supplied for an `else` statement)|\n",
"|`while`|while|while condition is true|\n",
"|`for`|for|execute in a loop for this many times|\n",
"|`try`|try|try this and run the `except` code if an error occurs|\n",
"\n",
"Let's take a look at each of these [flow control statement](https://docs.constellate.org/key-terms/#flow-control-statement) types."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `if` Statements\n",
"\n",
"An `if` statement begins with an [expression](https://docs.constellate.org/key-terms/#expression) that evaluates to **True** or **False**.\n",
"\n",
"* if **True**, then perform this action\n",
"* if **False**, skip over this action\n",
"\n",
"In practice, the form looks like this:\n",
"\n",
"`if this is True:`
\n",
" `perform this action`\n",
"\n",
"Let's put an `if` statement into practice with a very simple program that asks the user how their day is going and then responds. We can visualize the flow of the program in a flowchart.\n",
"\n",
"![Flowchart of a good day program](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/good_day_flowchart.png)\n",
"\n",
"Our program will use a single `if` statement. If the user types \"Yes\" or \"yes\", then our program will send a response."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A program that responds to a user having a good day\n",
"having_good_day = input('Are you having a good day? (Yes or No) ') # Define a variable having_good_day to hold the user's input in a string\n",
"\n",
"if having_good_day == 'Yes' or having_good_day == 'yes': # If the user has input the string 'Yes' or 'yes'\n",
" print('Glad to hear your day is going well!') # Print: Glad to hear your day is going well!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our program works fairly well so long as the user inputs 'Yes' or 'yes'. If they type 'no' or something else, it simply ends. If we want to have our program still respond, we can use an `else` statement."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `else` Statements\n",
"\n",
"An `else` statement *does not require a condition* to evaluate to **True** or **False**. It simply executes when none of the previous conditions are met. The form looks like this:\n",
"\n",
"`else:`
\n",
" `perform this action`\n",
"\n",
"Our updated flowchart now contains a second branch for our program.\n",
"\n",
"![The program flowchart with two branches](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/good_day_flowchart2.png)\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A program that responds to whether the user is having a good or bad day\n",
"having_good_day = input('Are you having a good day? (Yes or No) ') # Define a variable having_good_day to hold the user's input\n",
"\n",
"if having_good_day == 'Yes' or having_good_day == 'yes': # If the user has input the string 'Yes' or 'yes'\n",
" print('Glad to hear your day is going well!') # Print: Glad to hear your day is going well!\n",
" \n",
"# Write an else statement here\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our new program is more robust. The new `else` statement still gives the user a response if they do not respond \"Yes\" or \"yes\". But what if we wanted to add an option for when a user says \"No\"? Or when a user inputs something besides \"Yes\" or \"No\"? We could use a series of `elif` statements."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `elif` Statements\n",
"\n",
"An `elif` statement, short for \"else if,\" allows us to create a list of possible conditions where one (and only one) action will be executed. `elif` statements come after an initial `if` statement and before an `else` statement:\n",
"\n",
"`if condition A is True:`
\n",
" `perform action A`
\n",
"`elif condition B is True:`
\n",
" `perform action B`
\n",
"`elif condition C is True:`
\n",
" `perform action C`
\n",
"`elif condition D is True:`
\n",
" `perform action D`
\n",
"`else:`
\n",
" `perform action E`\n",
"\n",
"For example, we could add an `elif` statement to our program so it responds to both \"Yes\" and \"No\" with unique answers. We could then add an `else` statement that responds to any user input that is not \"Yes\" or \"No\".\n",
"\n",
"![Flowchart showing three branches](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/good_day_flowchart3.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A program that responds to whether the user is having a good or bad day\n",
"having_good_day = input('Are you having a good day? (Yes or No) ') # Define a variable having_good_day to hold the user's input\n",
"\n",
"if having_good_day == 'Yes' or having_good_day == 'yes': # If the user has input the string 'Yes' or 'yes'\n",
" print('Glad to hear your day is going well!') # Print: Glad to hear your day is going well!\n",
"\n",
"# Write and elif statement for having_good_day == 'No'\n",
"\n",
"\n",
"# An else statement that catches if the answer is not 'yes' or 'no'\n",
"else: # Execute this if none of the other branches executes\n",
" print('Sorry, I only understand \"Yes\" or \"No\"') # Note that we can use double quotations in our string because it begins and ends with single quotes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### The difference between`elif` and `if`?\n",
"\n",
"When an `elif` condition is met, all other `elif` statements are skipped over. This means that one (and only one) [flow control statement](https://docs.constellate.org/key-terms/#flow-control-statement) is executed when using `elif` statements. The fact that only one `elif` statement is executed is important because it may be possible for multiple [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) to evaluate to **True**. A series of `elif` statements evaluates from top-to-bottom, only executing the first `elif` statement whose condition evaluates to **True**. The rest of the `elif` statements are skipped over (whether they are **True** or **False**).\n",
"\n",
"In practice, a set of mutually exclusive `if` statements will result in the same actions as an `if` statement followed by `elif` statements. There are a few good reasons, however, to use `elif` statements:\n",
"\n",
"1. A series of `elif` statements helps someone reading your code understand that a single flow control choice is being made.\n",
"2. Using `elif` statements will make your program run faster since other conditional statements are skipped after the first evaluates to **True**. Otherwise, every `if` statement has to be evaluated before the program moves to the next step.\n",
"3. Writing a mutually exclusive set of `if` statements can be very complex.\n",
"\n",
"Expanding on the concept of our \"How is your day going?\" program, let's take a look at an example that asks the user \"How is your week going?\" It will take two inputs: the day of the week (`day_of_week`) and how the user feels the week is going (`having_good_week`).\n",
"\n",
"![How is your week going flowchart](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/good_week_elif.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A program that responds to the user's input for the day of the week and how their week is going.\n",
"day_of_week = input('What day of the week is it? ') \n",
"having_good_week = input('Are you having a good week? ')\n",
"\n",
"if day_of_week == 'Friday' or day_of_week == 'friday':\n",
" print('Enjoy the weekend!')\n",
" \n",
"elif having_good_week == 'Yes' or having_good_week == 'yes':\n",
" print('I hope the rest of the week is good too!')\n",
" \n",
"elif having_good_week == 'No' or having_good_week == 'no':\n",
" print('Sorry to hear that. I hope the rest of the week is better.')\n",
" \n",
"else:\n",
" print('Sorry, I only understand \"Yes\" or \"No\"')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the program above, try changing the `elif` statements to `if` statements. What happens if the user inputs 'Friday' and 'Yes'?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `while` Loop Statements\n",
"\n",
"So far, we have used [flow control statements](https://docs.constellate.org/key-terms/#flow-control-statement) like decision-making branches to decide what action should be taken next. Sometimes, however, we want a particular action to loop (or repeat) until some condition is met. We can accomplish this with a `while` loop statement that takes the form:\n",
"\n",
"`while condition is True:`
\n",
" `take this action`\n",
"\n",
"After the [code block](https://docs.constellate.org/key-terms/#code-block) is executed, the program loops back to check and see if the `while` loop condition has changed from **True** to **False**. The code block stops looping when the condition becomes **False**.\n",
"\n",
"In the following program, the user will guess a number until they get it correct. \n",
"\n",
"![flowchart for number-guessing program](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/guess_number_flowchart.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"# A program that asks the user to guess a number\n",
"\n",
"# The secret number is set here by the programmer.\n",
"secret_number = str(4) # We convert the integer to a string to compare easily with a user input string\n",
"\n",
"# Ask the user to make a guess and take input in a string\n",
"guess = input('I am thinking of a number between 1-10. Can you guess it? ') # Take the user's first guess\n",
"\n",
"# Check to see if the user guess matches our secret number\n",
"while guess != secret_number: # While the users guess does not equal secret_number\n",
" guess = input('Nope. Guess again! ') # Allow the user to change the value of guess\n",
"\n",
"print('You guessed the secret number, ' + secret_number) # Print a congratulations message with the secret number"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Stopping Accidental Infinite Loops\n",
"When using a `while` loop, it is possible to accidentally create an infinite loop that never ends. This happens because the `while` condition *never* becomes **False**. \n",
"\n",
"If you accidentally write code that infinitely repeats, you can stop the execution by selecting **Interrupt** from the **Kernel** menu. (Alternatively, you can press the letter **i** twice on your keyboard.) You may also want to remove the output of the rogue cell. You can do this from the **Cell** menu.\n",
"* Clearing output from a single cell: **Cell** ▶ **Current Outputs** ▶ **Clear**\n",
"* Clearing output from all cells: **Cell** ▶ **All Output** ▶ **Clear**\n",
"\n",
"![Clearing current outputs](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/clear_output.gif)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Run this infinite loop then interrupt the kernel\n",
"# Can you clear the cell output?\n",
"while True:\n",
" print('Oh noes!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### A Repeating `while` Loop\n",
"\n",
"In the program above, the `while` loop checked to see if the user guessed a particular number. We could also use a `while` loop to repeat a [code block](https://docs.constellate.org/key-terms/#code-block) a particular number of times."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A simple program that prints out 1, 2, 3\n",
"number = 0\n",
"while number < 3:\n",
" number = number + 1 # We can also write an equivalent shortcut: number += 1\n",
" print(number)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `for` Loop Statements with a `range()` Function\n",
"\n",
"An abbreviated way to write a `while` loop that repeats a specified number of times is using a `for` loop with a `range()` function. This loop takes the form:\n",
"\n",
"`for i in range(j):`
\n",
" `take this action`\n",
" \n",
"where `i` is a generic [variable](https://docs.constellate.org/key-terms/#variable) for counting the number of iterations and `j` is the number of times you want the [code block](https://docs.constellate.org/key-terms/#code-block) to repeat.\n",
"\n",
"The starting value of `i` is 0. After each loop, `i` increases by one until it reaches `j`. The loop then stops. The [variable](https://docs.constellate.org/key-terms/#variable) names `i` and `j` are merely conventions. Using a different name may make the purpose of your code clearer to readers."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A `for` loop that repeats 'What?' three times. \n",
"# How could you make this repeat five times?\n",
"# What happens if you change the name of variable `i`?\n",
"\n",
"for i in range(3):\n",
" print('What?')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A `for` loop that prints the value of the current iteration, here called `i`. \n",
"for i in range(5):\n",
" print(i)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the examples above, the `range()` [function](https://docs.constellate.org/key-terms/#function) takes a single argument that specifies the number of loops. The assumption is our `range()` [function](https://docs.constellate.org/key-terms/#function) will start at 0, but we can specify any starting [integer](https://docs.constellate.org/key-terms/#integer) by adding an additional [argument](https://docs.constellate.org/key-terms/#argument)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A `for` loop that starts looping at 27 and stops looping at 32\n",
"for i in range(27, 32):\n",
" print(i)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A `for` loop that starts looping at -3 and stops looping at 7\n",
"for i in range(-3, 7):\n",
" print(i)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also specify the size of each step for the `range()` [function](https://docs.constellate.org/key-terms/#function). In the above examples, the [function](https://docs.constellate.org/key-terms/#function) adds one for each increment step, but we can add larger numbers or even specify negative numbers to have the `range()` [function](https://docs.constellate.org/key-terms/#function) count down. The general form is:\n",
"\n",
"`for i in range(start, stop, increment):`
\n",
" `take this action`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A `for` loop that counts down from ten to one, followed by printing `Go!`\n",
"for i in range(10, 0, -1):\n",
" print(i)\n",
"print('Go!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `Continue` and `Break` Statements\n",
"`while` loops and `for` loops can also use `continue` and `break` statements to affect flow control. \n",
"* A `continue` statement immediately restarts the loop.\n",
"* A `break` statement immediately exits the loop.\n",
"\n",
"Let's return to our secret number guessing program. We will write the same program workflow using `continue` and `break` statements.\n",
"\n",
"![Flowchart for secret number guessing program](https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/guess_number_flowchart.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# A program that asks the user to guess a number\n",
"\n",
"# Initialize the variables `guess` and `secret_number`\n",
"guess = 0\n",
"secret_number = str(4) # The secret number is set here by the programmer. Notice it is turned into a string so it can be easily compared with user inputs.\n",
"\n",
"# Ask the user to make a guess\n",
"print('I am thinking of a number between 1-10.') \n",
"\n",
"# Test whether the user guess matches `secret_number`\n",
"while True:\n",
" guess = input('What is your guess? ')\n",
" if guess == secret_number:\n",
" break\n",
" else:\n",
" continue\n",
" \n",
" \n",
"# After loop ends, print a congratulations message with the secret number \n",
"print('You guessed the secret number, ' + secret_number) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exception Handling with `try` and `except`\n",
"\n",
"When running code that may create an error, we can use `try` and `except` statements to stop a program from crashing."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Try running the first code block, if there's an error then run the `except` code\n",
"# Divide 100 by a number the user chooses\n",
"\n",
"user_number = input('100 divided by ... ')\n",
"try:\n",
" print(100 / int(user_number))\n",
"except:\n",
" print(\"You can't divide by zero.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"