|
5 | 5 | "metadata": {}, |
6 | 6 | "source": [ |
7 | 7 | "# Conditional Statements\n", |
| 8 | + "\n", |
| 9 | + "<div class=\"alert alert-warning\">\n", |
| 10 | + "\n", |
| 11 | + "**Note**: \n", |
| 12 | + "\n", |
| 13 | + "There are reading-comprehension exercises included throughout the text. These are meant to help you put your reading to practice. Solutions for the exercises are included at the bottom of this page.\n", |
| 14 | + "</div>\n", |
| 15 | + "\n", |
| 16 | + "\n", |
8 | 17 | "In this section, we will be introduced to the `if`, `else`, and `elif` statements. These allow you to specify that blocks of code are to be executed only if specified conditions are found to be true, or perhaps alternative code if the condition is found to be false. \n", |
9 | 18 | "\n", |
10 | 19 | "Please refer to the \"Basic Python Object Types\" subsection to recall the basics of the \"boolean\" type, which represents True and False. We will extend that discussion by introducing comparison operations and membership-checking, and then expanding on the utility of the built-in `bool` type. " |
|
48 | 57 | "```python\n", |
49 | 58 | ">>> 2 < 3 < 1 # performs (2 < 3) and (3 < 1)\n", |
50 | 59 | "False\n", |
51 | | - "```" |
52 | | - ] |
53 | | - }, |
54 | | - { |
55 | | - "cell_type": "markdown", |
56 | | - "metadata": {}, |
57 | | - "source": [ |
58 | | - "## Testing for Membership in Collections: `in` and `not in`\n", |
59 | | - "The `in` and `not in` statements are a built-in operator for *testing for membership in a collection of items*. For example:\n", |
| 60 | + "```\n", |
| 61 | + "\n", |
| 62 | + "Whereas `==` checks to see if two objects have the same value, the `is` operator checks to see if two objects are actually the *same* object. For example, creating two lists with the same contents produces two *distinct* lists, that have the same \"value\":\n", |
60 | 63 | "\n", |
61 | 64 | "```python\n", |
62 | | - ">>> 2 in [3, 2, 0] # test for membership in a list\n", |
| 65 | + "# demonstrating `==` vs `is`\n", |
| 66 | + ">>> x = [1, 2, 3]\n", |
| 67 | + ">>> y = [1, 2, 3]\n", |
| 68 | + "\n", |
| 69 | + ">>> x == y\n", |
63 | 70 | "True\n", |
64 | 71 | "\n", |
65 | | - ">>> 3 not in (-2, -1, 0) # test for membership in a tuple\n", |
| 72 | + "# `x` and `y` reference equivalent, but distinct lists\n", |
| 73 | + ">>> x is y\n", |
| 74 | + "False\n", |
| 75 | + "```\n", |
| 76 | + "\n", |
| 77 | + "Thus the `is` operator is most commonly used to check if a variable references the `None` object, or either of the boolean objects:\n", |
| 78 | + "```python\n", |
| 79 | + ">>> x = None\n", |
| 80 | + ">>> x is None\n", |
66 | 81 | "True\n", |
67 | 82 | "\n", |
68 | | - ">>> \"a\" in \"apple\" # test for membership in a string\n", |
| 83 | + "# (2 < 0) returns the object `False`\n", |
| 84 | + "# thus this becomes: `False is False`\n", |
| 85 | + ">>> (2 < 0) is False\n", |
69 | 86 | "True\n", |
70 | 87 | "```\n", |
71 | 88 | "\n", |
72 | | - "Whenever possible, Python uses efficient algorithms for testing membership, as invoked by `in` and `not in`." |
| 89 | + "Use `is not` to check if two objects are distinct:\n", |
| 90 | + "```python\n", |
| 91 | + ">>> 1 is not None\n", |
| 92 | + "True\n", |
| 93 | + "```" |
73 | 94 | ] |
74 | 95 | }, |
75 | 96 | { |
|
124 | 145 | "metadata": {}, |
125 | 146 | "source": [ |
126 | 147 | "## `if`, `else`, and `elif`\n", |
127 | | - "We now introduce the simple, but powerful `if`, `else`, and `elif` conditional statements. The following pseudo-code demonstrates their general usage:\n", |
| 148 | + "We now introduce the simple, but powerful `if`, `else`, and `elif` conditional statements. This will allow us to create simple branches in our code. For instance, suppose you are writing code for a videogame, and you want to update a character's status based on her/his number of health-points (an integer). The following code is representative of this:\n", |
| 149 | + "\n", |
| 150 | + "```python\n", |
| 151 | + "if num_health > 80:\n", |
| 152 | + " status = \"good\"\n", |
| 153 | + "elif num_health > 50:\n", |
| 154 | + " status = \"okay\"\n", |
| 155 | + "elif num_health > 0:\n", |
| 156 | + " status = \"danger\"\n", |
| 157 | + "else:\n", |
| 158 | + " status = \"dead\"\n", |
| 159 | + "```\n", |
| 160 | + "\n", |
| 161 | + "The following pseudo-code demonstrates their general template for conditional statements:\n", |
128 | 162 | "\n", |
129 | 163 | "```\n", |
130 | 164 | "if <expression_1>:\n", |
|
155 | 189 | "```python\n", |
156 | 190 | "x = [1, 2]\n", |
157 | 191 | "\n", |
158 | | - "if 3 < len(x): # bool(3 < 2) returns False\n", |
| 192 | + "if 3 < len(x):\n", |
| 193 | + " # bool(3 < 2) returns False, this code \n", |
| 194 | + " # block is skipped\n", |
159 | 195 | " print(\"`x` has more than three items in it\")\n", |
160 | | - "elif len(x) == 2 # bool(len(x) == 2) returns True\n", |
| 196 | + "elif len(x) == 2\n", |
| 197 | + " # bool(len(x) == 2) returns True\n", |
| 198 | + " # this code block is executed\n", |
161 | 199 | " print(\"`x` has two items in it\")\n", |
162 | | - "elif len(x) == 1 # this statement is never reached\n", |
| 200 | + "elif len(x) == 1\n", |
| 201 | + " # this statement is never reached\n", |
163 | 202 | " print(\"`x` has one items in it\")\n", |
164 | | - "else: # this statement is never reached\n", |
| 203 | + "else:\n", |
| 204 | + " # this statement is never reached\n", |
165 | 205 | " print(\"`x` is an empty list\")\n", |
166 | 206 | "\n", |
167 | 207 | "\"`x` has two items in it\"\n", |
|
178 | 218 | "if x < 0:\n", |
179 | 219 | " x = x ** 2\n", |
180 | 220 | "# x is now 1\n", |
181 | | - "```\n", |
| 221 | + "```\n" |
| 222 | + ] |
| 223 | + }, |
| 224 | + { |
| 225 | + "cell_type": "code", |
| 226 | + "execution_count": 21, |
| 227 | + "metadata": {}, |
| 228 | + "outputs": [], |
| 229 | + "source": [ |
| 230 | + "my_file = \"code.pdf\"\n", |
182 | 231 | "\n", |
183 | | - "#### Pitfall: Variable Assignment in Conditional Contexts\n", |
184 | | - "It is worth pointing out a \"dangerous\" code design pattern, which is to assign a variable conditionally. Take the following code for example:\n", |
| 232 | + "if \".\" in my_file:\n", |
| 233 | + " dot_index = my_file.index(\".\")\n", |
| 234 | + " filename = my_file[:dot_index]\n", |
| 235 | + "else:\n", |
| 236 | + " filename = my_file" |
| 237 | + ] |
| 238 | + }, |
| 239 | + { |
| 240 | + "cell_type": "code", |
| 241 | + "execution_count": 22, |
| 242 | + "metadata": {}, |
| 243 | + "outputs": [ |
| 244 | + { |
| 245 | + "data": { |
| 246 | + "text/plain": [ |
| 247 | + "'code'" |
| 248 | + ] |
| 249 | + }, |
| 250 | + "execution_count": 22, |
| 251 | + "metadata": {}, |
| 252 | + "output_type": "execute_result" |
| 253 | + } |
| 254 | + ], |
| 255 | + "source": [ |
| 256 | + "filename" |
| 257 | + ] |
| 258 | + }, |
| 259 | + { |
| 260 | + "cell_type": "markdown", |
| 261 | + "metadata": {}, |
| 262 | + "source": [ |
| 263 | + "***\n", |
| 264 | + "\n", |
| 265 | + "**Reading Comprehension: Conditional statements**\n", |
185 | 266 | "\n", |
| 267 | + "1\\. Assume `my_list` is a list. Given the following code:\n", |
186 | 268 | "```python\n", |
187 | | - "# assume x and y have not yet been defined\n", |
188 | | - "if 0 <= z:\n", |
189 | | - " x = 1\n", |
190 | | - "else:\n", |
191 | | - " y = 1\n", |
| 269 | + "first_item = None\n", |
| 270 | + "\n", |
| 271 | + "if my_list:\n", |
| 272 | + " first_item = my_list[0]\n", |
192 | 273 | "```\n", |
193 | 274 | "\n", |
194 | | - "Any code following this \"if-else\" block is in a perilous state: `y` is never defined if `z` is positive, in which case any subsequent code referencing `y` will raise an error. Similarly, `x` will never be defined if `z` is negative. *Never define a variable conditionally*." |
| 275 | + "What will happen if `my_list` is `[]`? Will `IndexError` be raised? What will `first_item` be?\n", |
| 276 | + "\n", |
| 277 | + "2\\. The variable `my_file` is a string like `\"code.py\"`, `\"my_doc.txt\"`, etc, where a period demarks the end of the file-name and the beginning of the file-type. `my_file` will have at most one period in it. Write code that creates a variable which stores only the filename. Accomodate cases where `my_file` does *not* include a file-type. \n", |
| 278 | + "\n", |
| 279 | + "That is, `\"code.py\"` $\\rightarrow$ `\"code\"`, `\"doc2.pdf\"` $\\rightarrow$ `\"doc2\"`, `\"hello_world\"` $\\rightarrow$ `\"hello_world\"` \n", |
| 280 | + "***" |
195 | 281 | ] |
196 | 282 | }, |
197 | 283 | { |
|
232 | 318 | "# will append 0 to `my_list if `x` is negative\n", |
233 | 319 | "my_list.append(1 if x >= 0 else 0)\n", |
234 | 320 | "```\n", |
| 321 | + "```python\n", |
| 322 | + ">>> x = 2\n", |
| 323 | + ">>> \"a\" if x == 1 else \"b\"\n", |
| 324 | + "\"b\n", |
| 325 | + "```\n", |
235 | 326 | "We will see this syntax shine when we learn about comprehension statements. That being said, this syntax should be used judiciously. For example, inline if-else statements ought not be used in arithmetic expressions, for therein lies madness:\n", |
236 | 327 | "\n", |
237 | 328 | "```python\n", |
238 | 329 | "# don't ever do this...ever!\n", |
239 | 330 | "2 - 3 if x < 1 else 1 + 6*2 if x >= 0 else 9\n", |
240 | 331 | "```" |
241 | 332 | ] |
| 333 | + }, |
| 334 | + { |
| 335 | + "cell_type": "markdown", |
| 336 | + "metadata": {}, |
| 337 | + "source": [ |
| 338 | + "## Reading Comprehension Exercise Solutions:" |
| 339 | + ] |
| 340 | + }, |
| 341 | + { |
| 342 | + "cell_type": "markdown", |
| 343 | + "metadata": {}, |
| 344 | + "source": [ |
| 345 | + "**Conditional statements**\n", |
| 346 | + "\n", |
| 347 | + "1\\. If `my_list` is `[]`, then `bool(my_list)` will return `False`, and the code block will be skipped. Thus `first_item` will be `None`.\n", |
| 348 | + "\n", |
| 349 | + "2\\. First, check to see if `.` is even contained in `my_file`. If it is, find its index-position, and slice the string up to that index. Otherwise, `my_file` is already the file name.\n", |
| 350 | + "```python\n", |
| 351 | + "\n", |
| 352 | + "my_file = \"code.pdf\"\n", |
| 353 | + "\n", |
| 354 | + "if \".\" in my_file:\n", |
| 355 | + " dot_index = my_file.index(\".\")\n", |
| 356 | + " filename = my_file[:dot_index]\n", |
| 357 | + "else:\n", |
| 358 | + " filename = my_file\n", |
| 359 | + "```" |
| 360 | + ] |
242 | 361 | } |
243 | 362 | ], |
244 | 363 | "metadata": { |
|
0 commit comments