{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Control Flow\n",
"============\n",
"\n",
"Basics\n",
"------\n",
"\n",
"For a given file with a python program, the python interpreter will start at the top and then process the file. We demonstrate this with a simple program, for example:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Main program starts here\n",
"4 * 4 = 16\n",
"In last line of program -- bye\n"
]
}
],
"source": [
"def f(x):\n",
" \"\"\"function that computes and returns x*x\"\"\"\n",
" return x * x\n",
"\n",
"print(\"Main program starts here\")\n",
"print(\"4 * 4 = %s\" % f(4))\n",
"print(\"In last line of program -- bye\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The basic rule is that commands in a file (or function or any sequence of commands) is processed from top to bottom. If several commands are given in the same line (separated by `;`), then these are processed from left to right (although it is discouraged to have multiple statements per line to maintain good readability of the code.)\n",
"\n",
"In this example, the interpreter starts at the top (line 1). It finds the `def` keyword and remembers for the future that the function `f` is defined here. (It will not yet execute the function body, i.e. line 3 – this only happens when we call the function.) The interpreter can see from the indentation where the body of the function stops: the indentation in line 5 is different from that of the first line in the function body (line2), and thus the function body has ended, and execution should carry on with that line. (Empty lines do not matter for this analysis.)\n",
"\n",
"In line 5 the interpreter will print the output `Main program starts here`. Then line 6 is executed. This contains the expression `f(4)` which will call the function `f(x)` which is defined in line 1 where `x` will take the value `4`. \\[Actually `x` is a reference to the object `4`.\\] The function `f` is then executed and computes and returns `4*4` in line 3. This value `16` is used in line 6 to replace `f(4)` and then the string representation `%s` of the object 16 is printed as part of the print command in line 6.\n",
"\n",
"The interpreter then moves on to line 7 before the program ends.\n",
"\n",
"We will now learn about different possibilities to direct this control flow further.\n",
"\n",
"### Conditionals\n",
"\n",
"The python values `True` and `False` are special inbuilt objects:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"source": [
"a = True\n",
"print(a)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"bool"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(a)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n"
]
}
],
"source": [
"b = False\n",
"print(b)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"bool"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can operate with these two logical values using boolean logic, for example the logical and operation (`and`):"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"True and True #logical and operation"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"True and False"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"False and True"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"True and True"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n"
]
}
],
"source": [
"c = a and b\n",
"print(c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There is also logical or (`or`) and the negation (`not`):"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"True or False"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"not True"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"not False"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"True and not False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In computer code, we often need to evaluate some expression that is either true or false (sometimes called a “predicate”). For example:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = 30 # assign 30 to x\n",
"x > 15 # is x greater than 15"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x > 42"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x == 30 # is x the same as 30?"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x == 42"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"not x == 42 # is x not the same as 42?"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x != 42 # is x not the same as 42?"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x > 30 # is x greater than 30?"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x >= 30 # is x greater than or equal to 30?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If-then-else\n",
"------------\n",
"\n",
"##### Further information\n",
"\n",
"- Introduction to If-then in [Python tutorial, section 4.1](http://docs.python.org/tutorial/controlflow.html#if-statements)\n",
"\n",
"The `if` statement allows conditional execution of code, for example:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a is positive\n"
]
}
],
"source": [
"a = 34\n",
"if a > 0:\n",
" print(\"a is positive\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The if-statement can also have an `else` branch which is executed if the condition is wrong:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a is positive\n"
]
}
],
"source": [
"a = 34\n",
"if a > 0:\n",
" print(\"a is positive\")\n",
"else:\n",
" print(\"a is non-positive (i.e. negative or zero)\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, there is the `elif` (read as “else if”) keyword that allows checking for several (exclusive) possibilities:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a is positive\n"
]
}
],
"source": [
"a = 17\n",
"if a == 0:\n",
" print(\"a is zero\")\n",
"elif a < 0:\n",
" print(\"a is negative\")\n",
"else:\n",
" print(\"a is positive\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For loop\n",
"--------\n",
"\n",
"##### Further information\n",
"\n",
"- Introduction to for-loops in [Python tutorial, section 4.2](http://docs.python.org/tutorial/controlflow.html#for-statements)\n",
"\n",
"The `for`-loop allows to iterate over a sequence (this could be a string or a list, for example). Here is an example:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dog DOG\n",
"cat CAT\n",
"mouse MOUSE\n"
]
}
],
"source": [
"for animal in ['dog','cat','mouse']:\n",
" print(animal, animal.upper())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Together with the `range()` command ([in chapter 3](03-data-types-structures.ipynb#The-range()-command)), one can iterate over increasing integers:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5\n",
"6\n",
"7\n",
"8\n",
"9\n"
]
}
],
"source": [
"for i in range(5,10):\n",
" print(i)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"While loop\n",
"----------\n",
"\n",
"The `while` keyword allows to repeat an operation while a condition is true. Suppose we’d like to know for how many years we have to keep 100 pounds on a savings account to reach 200 pounds simply due to annual payment of interest at a rate of 5%. Here is a program to compute that this will take 15 years:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"We need 15 years to reach 207.89281794113688 pounds.\n"
]
}
],
"source": [
"mymoney = 100 # in GBP\n",
"rate = 1.05 # 5% interest\n",
"years = 0\n",
"while mymoney < 200: # repeat until 20 pounds reached\n",
" mymoney = mymoney * rate\n",
" years = years + 1\n",
"print('We need', years, 'years to reach', mymoney, 'pounds.')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Relational operators (comparisons) in `if` and `while` statements\n",
"-------------------------------------------------------------------------------------------\n",
"\n",
"The general form of `if` statements and `while` loops is the same: following the keyword `if` or `while`, there is a *condition* followed by a colon. In the next line, a new (and thus indented!) block of commands starts that is executed if the condition is True).\n",
"\n",
"For example, the condition could be equality of two variables `a1` and `a2` which is expressed as `a1==a2`:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a1 and a2 are the same\n"
]
}
],
"source": [
"a1 = 42\n",
"a2 = 42\n",
"if a1 == a2:\n",
" print(\"a1 and a2 are the same\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another example is to test whether `a1` and `a2` are not the same. For this, we have two possibilities. Option number 1 uses the *inequality operator* `!=`:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"if a1 != a2:\n",
" print(\"a1 and a2 are different\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Option two uses the keyword `not` in front of the condition:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"if not a1 == a2:\n",
" print(\"a1 and a2 are different\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Comparisons for “greater” (`>`), “smaller” (`<`) and “greater equal” (`>=`) and “smaller equal” (`<=`) are straightforward.\n",
"\n",
"Finally, we can use the logical operators “`and`” and “`or`” to combine conditions:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Either a is greater than 10, or b is smaller than -5, or both.\n"
]
}
],
"source": [
"if a > 10 and b > 20:\n",
" print(\"A is greater than 10 and b is greater than 20\")\n",
"if a > 10 or b < -5:\n",
" print(\"Either a is greater than 10, or \"\n",
" \"b is smaller than -5, or both.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use the Python prompt to experiment with these comparisons and logical expressions. For example:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"quite cold\n"
]
}
],
"source": [
"T = -12.5\n",
"if T < -20:\n",
" print(\"very cold\")\n",
"\n",
"if T < -10:\n",
" print(\"quite cold\")"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T < -20"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T < -10"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Exceptions\n",
"----------\n",
"\n",
"Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made to execute it. Errors detected during execution are called *exceptions* and are not necessarily fatal: exceptions can be *caught* and dealt with within the program. Most exceptions are not handled by programs, however, and result in error messages as shown here"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "ZeroDivisionError",
"evalue": "division by zero",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m10\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mZeroDivisionError\u001b[0m: division by zero"
]
}
],
"source": [
"10 * (1/0)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'spam' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m4\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mspam\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mNameError\u001b[0m: name 'spam' is not defined"
]
}
],
"source": [
"4 + spam*3"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "TypeError",
"evalue": "Can't convert 'int' object to str implicitly",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;34m'2'\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m: Can't convert 'int' object to str implicitly"
]
}
],
"source": [
"'2' + 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Schematic exception catching with all options"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "IndentationError",
"evalue": "expected an indented block (, line 3)",
"output_type": "error",
"traceback": [
"\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m3\u001b[0m\n\u001b[0;31m except ArithmeticError:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m expected an indented block\n"
]
}
],
"source": [
"try:\n",
" # code body\n",
"except ArithmeticError:\n",
" # what to do if arithmetic error\n",
"except IndexError, the_exception:\n",
" # the_exception refers to the exeption in this block\n",
"except:\n",
" # what to do for ANY other exception\n",
"else: # optional\n",
" # what to do if no exception raised\n",
"\n",
"try:\n",
" # code body\n",
"finally:\n",
" # what to do ALWAYS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with Python 2.5, you can use the with statement to simplify the writing of code for some predefined functions, in particular the `open` function to open files: see .\n",
"\n",
"Example: We try to open a file that does not exist, and Python will raise an exception of type `IOError` which stands for Input Output Error:"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "FileNotFoundError",
"evalue": "[Errno 2] No such file or directory: 'filenamethatdoesnotexist'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"filenamethatdoesnotexist\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"r\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'filenamethatdoesnotexist'"
]
}
],
"source": [
"f = open(\"filenamethatdoesnotexist\", \"r\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we were writing an application with a userinterface where the user has to type or select a filename, we would not want to application to stop if the file does not exist. Instead, we need to catch this exception and act accordingly (for example by informing the user that a file with this filename does not exist and ask whether they want to try another file name). Here is the skeleton for catching this exception:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Could not open that file\n"
]
}
],
"source": [
"try:\n",
" f = open(\"filenamethatdoesnotexist\",\"r\")\n",
"except IOError:\n",
" print(\"Could not open that file\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There is a lot more to be said about exceptions and their use in larger programs. Start reading [Python Tutorial Chapter 8: Errors and Exceptions](http://docs.python.org/tutorial/errors.html#errors-and-exceptions) if you are interested.\n",
"\n",
"### Raising Exceptions\n",
"\n",
"Raising exception is also referred to as ’throwing an exception’.\n",
"\n",
"Possibilities of raising an Exception\n",
"\n",
"- `raise OverflowError`\n",
"\n",
"- `raise OverflowError, Bath is full` (Old style, now discouraged)\n",
"\n",
"- `raise OverflowError(Bath is full)`\n",
"\n",
"- `e = OverflowError(Bath is full); raise e`\n",
"\n",
"#### Exception hierarchy\n",
"\n",
"The standard exceptions are organized in an inheritance hierarchy e.g. OverflowError is a subclass of ArithmeticError (not BathroomError); this can be seen when looking at `help(’exceptions’)` for example.\n",
"\n",
"You can derive your own exceptions from any of the standard ones. It is good style to have each module define its own base exception."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Creating our own exceptions\n",
"\n",
"- You can and should derive your own exceptions from the built-in Exception.\n",
"\n",
"- To see what built-in exceptions exist, look in the module exceptions (try `help(’exceptions’)`), or go to .\n",
"\n",
"### LBYL vs EAFP\n",
"\n",
"- LBYL (Look Before You Leap) vs\n",
"\n",
"- EAFP (Easer to ask forgiveness than permission)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"numerator = 7\n",
"denominator = 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Example for LBYL:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Oops\n"
]
}
],
"source": [
"if denominator == 0:\n",
" print(\"Oops\")\n",
"else:\n",
" print(numerator/denominator)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Easier to Ask for Forgiveness than Permission:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Oops\n"
]
}
],
"source": [
"try:\n",
" print(numerator/denominator)\n",
"except ZeroDivisionError:\n",
" print(\"Oops\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Python documentation says about EAFP:\n",
"\n",
"> Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.\n",
"\n",
"Source: \n",
"\n",
"The Python documentation says about LBYL:\n",
"\n",
"> Look before you leap. This coding style explicitly tests for pre-conditions before making calls or lookups. This style contrasts with the EAFP approach and is characterized by the presence of many if statements.\n",
">\n",
"> In a multi-threaded environment, the LBYL approach can risk introducing a race condition between “the looking” and “the leaping”. For example, the code, if key in mapping: return mapping\\[key\\] can fail if another thread removes key from mapping after the test, but before the lookup. This issue can be solved with locks or by using the EAFP approach.\n",
"\n",
"Source: \n",
"\n",
"EAFP is the Pythonic way."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.4"
}
},
"nbformat": 4,
"nbformat_minor": 1
}