{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "*This notebook contains material for CBE 20258 Numerical and Statistical Analysis taught at the University of Notre Dame. (c) Professors Alexander Dowling, Ryan McClarren, and Yamil Colón. This collection of notebooks [cbe-xx258](https://ndcbe.github.io/cbe-xx258) is available [on Github](https://github.com/ndcbe/cbe-xx258).*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [1.3 Flow Control and Pseudocode](https://ndcbe.github.io/cbe-xx258/01.03-Flow-control.html) | [Contents](toc.html) | [1.5 List, Dictionaries, and Enumeration](https://ndcbe.github.io/cbe-xx258/01.05-Lists-Dictionaries-Enumerate.html) >

\"Open

\"Download\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# IMPORT DATA FILES USED BY THIS NOTEBOOK\n", "import os, requests\n", "\n", "file_links = [(\"data/fifth_republic.txt\", \"https://ndcbe.github.io/cbe-xx258/data/fifth_republic.txt\"),\n", " (\"data/hats.txt\", \"https://ndcbe.github.io/cbe-xx258/data/hats.txt\")]\n", "\n", "# This cell has been added by nbpages. Run this cell to download data files required for this notebook.\n", "\n", "for filepath, fileurl in file_links:\n", " stem, filename = os.path.split(filepath)\n", " if stem:\n", " if not os.path.exists(stem):\n", " os.mkdir(stem)\n", " if not os.path.isfile(filepath):\n", " with open(filepath, 'wb') as f:\n", " response = requests.get(fileurl)\n", " f.write(response.content)\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Z_7CzQztmUoo", "nbpages": { "level": 1, "link": "[1.4 Functions, Scoping, and Other Fun Stuff](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4-Functions,-Scoping,-and-Other-Fun-Stuff)", "section": "1.4 Functions, Scoping, and Other Fun Stuff" } }, "source": [ "# 1.4 Functions, Scoping, and Other Fun Stuff\n" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 1, "link": "[1.4 Functions, Scoping, and Other Fun Stuff](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4-Functions,-Scoping,-and-Other-Fun-Stuff)", "section": "1.4 Functions, Scoping, and Other Fun Stuff" } }, "source": [ "**Reference**: Chapter 3 of *Computational Nuclear Engineering and Radiological Science Using Python*, R. McClarren (2018) " ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.1 Learning Objectives](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.1-Learning-Objectives)", "section": "1.4.1 Learning Objectives" } }, "source": [ "## 1.4.1 Learning Objectives\n", "\n", "After studying this notebook, completing the activities, and asking questions in class, you should be able to:" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Vvv-zUXfmUop", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "## 1.4.2 Functions\n", "\n", "### Motivating Example" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "x5araXX7mUoq", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "Why use functions? We want to write, debug, and test code **once** and then **reuse** as much as possible.\n", "\n", "In a few class sessions, we'll formulate mass balances as linear systems and solve them using Python. But for now, let's just consider a problem you would expect to see in math class:\n", "\n", "We want to solve the linear system,\n", "\n", "$$\\mathrm{Eqn.~1}:\\quad 4.5 x + 3 y = 10.5\\\\\\mathrm{Eqn.~2}:\\quad 1.5 x + 3 y = 7.5.$$\n", "\n", "One way to do this is using Python as calculator. In the comments below, we walk through the steps." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 87 }, "colab_type": "code", "executionInfo": { "elapsed": 750, "status": "ok", "timestamp": 1548171075668, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "9F-6X4lhmUos", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" }, "outputId": "44077880-5b15-46b6-a4a3-9d43943c2c98" }, "outputs": [], "source": [ "\"\"\"python code to solve \n", "4.5 x + 3 y = 10.5\n", "1.5 x + 3 y = 7.5\n", "by solving the second equation for y first,\n", "and then solving for x\"\"\"\n", "#step 1 solve for y, multiply equation 2 by -3, \n", "## and add to first equation\n", "LHS_coefficient = -3*3 + 3 #the coefficient for y\n", "RHS = -3*7.5 + 10.5 #the right-hand side\n", "\n", "print('LHS_coefficient:',LHS_coefficient)\n", "print('RHS:',RHS)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "Mathematical, we started by multiplying equation 2,\n", "\n", "$$1.5 x + 3 y = 7.5$$\n", "\n", "by -3,\n", "\n", "$$(-3) \\times 1.5 x + (-3) \\times 3 y = (-3) \\times 7.5$$\n", "\n", "\n", "and then added this scaled equation 2 to equation 1, giving:\n", "\n", "$$(4.5 - 3 \\times 1.5) x + (3 - 3 \\times 3) y = 10.5 - 3 \\times 7.5$$\n", "\n", "Notice that our choice of scaling equation 2 by -3 means that the coefficient for x becomes zero after addition addition. The coefficient for $y$ is `LHS_coefficient` is our code. `RHS` is the right hand side of the new equation.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The solution to:\n", "4.5 x + 3 y = 10.5\n", "1.5 x + 3 y = 7.5\n", " is x = 1.0 y= 2.0\n" ] } ], "source": [ "#now divide right-hand side by left-hand side coefficient\n", "y = RHS / LHS_coefficient\n", "#plug y into first equation\n", "x = (10.5 - 3*y)/4.5 \n", "#print the solution, note \\n produces a linebreak\n", "print(\"The solution to:\\n4.5 x + 3 y = 10.5\\n1.5 x + 3 y = 7.5\\n is x =\",\n", " x,\"y=\",y)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "192rbx9dmUow", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "How to extend this code to another linear system?\n", "\n", "**Let's define a function** that will solve the system for (almost) any coefficients and right-hand side. \n", "\n", "I'll define such a function to solve $$a_1 x + b_1 y = c_1\\\\ a_2 x + b_2 y = c_2.$$" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "locked": false, "solution": false }, "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "

\n", "Home Activity: Write pseudocode to generalize the steps from the motivating example to solve the linear system with coefficients a1, a2, b1, b2, c1, and c2. Turn in your pseudocode via Gradescope. We will only look at your pseudocode for completeness and compliance with the formatting guidelines, not correctness.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "
\n", "Class Activity: Discuss your pseudocode with a partner. Give one compliment and one suggestion to partner's pseudocode. We'll then regroup and write it together as a class.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "Below is a function that solves (most) 2x2 linear systems. Take a few minutes to study the code below. Specifically:\n", "\n", "* Notice the function has seven inputs. The first six are the coefficients. The seventh, `LOUD`, is followed by `=False`. This sets the default value of `LOUD` to false.\n", "* The input `LOUD` toggles on/off a print statement.\n", "* This function has a long comment string at the top. It includes a brief description, then a list of inputs (arguments) and finally a list of outputs (returns). All of the functions you write in this class must be commented in the same style.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": {}, "colab_type": "code", "id": "iJy9onTMmUox", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "outputs": [], "source": [ "def two_by_two_solver(a1,b1,c1,a2,b2,c2, LOUD=False):\n", " \"\"\"Calculate the solution of the system \n", " a1 x + b1 y = c1, \n", " a2 x + b2 y = c2\n", "\n", " Args:\n", " a1: x coefficient in first equation (cannot be zero)\n", " b1: y coefficient in first equation\n", " c1: right-hand side in first equation\n", " a2: x coefficient in second equation \n", " b2: y coefficient in second equation \n", " c2: right-hand side in second equation\n", " LOUD: boolean that decides whether to print out the answer\n", " \n", " Returns:\n", " list containing the solution in the format [x,y]\n", " \"\"\"\n", " #step one, eliminate x from the second equation by \n", " #multiplying first equation by -a2/a1\n", " #and then adding it to second equation\n", " new_b2 = b2 - a2/a1*b1\n", " new_c2 = c2 - a2/a1*c1\n", " #solve the new equation 2\n", " y = new_c2/new_b2\n", " #plug y into original equation 1\n", " x = (c1-b1*y)/a1\n", " \n", " if (LOUD):\n", " print(\"The solution to:\\n\",a1,\"x +\",b1,\"y =\",c1,\n", " \"\\n\",a2,\"x +\",b2,\"y =\",c2,\"\\n is x =\",x,\"y=\",y)\n", " return [x,y]\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "7g_AZDN5mUo0", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "We can call this function for the problem above by typing" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 104 }, "colab_type": "code", "executionInfo": { "elapsed": 208, "status": "ok", "timestamp": 1548171182950, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "qGP8yIQ2mUo1", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" }, "outputId": "e3ee7b31-6d0c-4df2-f4d4-2cfdf7d8c13c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The solution to:\n", " 4.5 x + 3 y = 10.5 \n", " 1.5 x + 3 y = 7.5 \n", " is x = 1.0 y= 2.0\n" ] }, { "data": { "text/plain": [ "[1.0, 2.0]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "two_by_two_solver(4.5,3,10.5,1.5,3,7.5,True)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "p564Yo-FmUo4", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "We can also solve other systems, including simple ones" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 104 }, "colab_type": "code", "executionInfo": { "elapsed": 215, "status": "ok", "timestamp": 1548171191091, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "G1EZy58XmUo4", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" }, "outputId": "04ff9404-7000-4b22-922c-af04a38ce038" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The solution to:\n", " 1 x + 0 y = 3 \n", " 0 x + 1 y = 2 \n", " is x = 3.0 y= 2.0\n" ] }, { "data": { "text/plain": [ "[3.0, 2.0]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "two_by_two_solver(1,0,3,0,1,2,True)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "vL0v11TjmUo7", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" } }, "source": [ "We can't solve systems where $a_1$ is zero because our function divides by $a_1$:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 287 }, "colab_type": "code", "executionInfo": { "elapsed": 333, "status": "error", "timestamp": 1548171197526, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "AqY0_GTwmUo8", "nbpages": { "level": 2, "link": "[1.4.2 Functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2-Functions)", "section": "1.4.2 Functions" }, "outputId": "c599d0ef-92ea-4c93-efc3-f68bff7f0ce1" }, "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[0mtwo_by_two_solver\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\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;36m3\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mtwo_by_two_solver\u001b[0;34m(a1, b1, c1, a2, b2, c2, LOUD)\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;31m#multiplying first equation by -a2/a1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;31m#and then adding it to second equation\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0mnew_b2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mb2\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0ma2\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0ma1\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mb1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 22\u001b[0m \u001b[0mnew_c2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mc2\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0ma2\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0ma1\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mc1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;31m#solve the new equation 2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "two_by_two_solver(0,1,2,1,0,3,True)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "FTXAc9FgmUo-", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" } }, "source": [ "### 1.4.2.1 Calling functions" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "vGq1S_t3mUo_", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" } }, "source": [ "**Approach above: give inputs in order**\n", "\n", "We called the function two_by_two_solver by listing out the arguments in the order that it expects them a1, b1, c1, a2, b2, c2, LOUD.\n", "\n", "**Another option: use keywords**\n", "\n", "Python allows you to call them in any order, as long as you are explicit in what goes where." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 104 }, "colab_type": "code", "executionInfo": { "elapsed": 218, "status": "ok", "timestamp": 1548171250400, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "qLckFvibmUo_", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" }, "outputId": "f64d230f-71a1-4e8b-fe67-8f60f7274e8b" }, "outputs": [], "source": [ "two_by_two_solver(a1 = 4.5, b1 = 3, \n", " a2 = 1.5, b2 = 3, \n", " c1 = 10.5, c2 = 7.5, LOUD = True)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "8noqot07mUpC", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" } }, "source": [ "It is often a good idea to call a function explicitly (with keywords). That way if you mess up the order of the arguments, it does not matter.\n", "\n", "Notice that in the function definition, the argument LOUD has =False after it. This indicates that if the function is called without a value for LOUD, it assumes the caller does not what the function to \"be loud\".\n", "\n", "In other words, False is the **default** for argument LOUD." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "colab_type": "code", "executionInfo": { "elapsed": 213, "status": "ok", "timestamp": 1548171318534, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "AozXfTp0mUpD", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" }, "outputId": "c3c9f186-1a67-49c0-c3b6-415c3b3a0f02" }, "outputs": [], "source": [ "two_by_two_solver(a1 = 4.5, b1 = 3, a2 = 1.5, \n", " b2 = 3, c1 = 10.5, c2 = 7.5)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "a2As_U8HmUpG", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" } }, "source": [ "Notice that it did not print out it's spiel about the system." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "colab_type": "code", "executionInfo": { "elapsed": 246, "status": "ok", "timestamp": 1548171329182, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "N4H8ulKOmUpG", "nbpages": { "level": 3, "link": "[1.4.2.1 Calling functions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.1-Calling-functions)", "section": "1.4.2.1 Calling functions" }, "outputId": "3656a5b5-abc6-45e0-ae2d-a7411bb88a01" }, "outputs": [], "source": [ "two_by_two_solver(1,1,2,a2 = 1, c2 = 0, b2 = 3)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "U4M2x2kAmUpJ", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "### 1.4.2.2 Return Values" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "t7t-NP3tmUpJ", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "At the end of the function we have a return statement. This tells python what the function is returning to the caller. In this case we return a list that has the solution for $x$ and $y$. We can store this in a new variable, or do whatever we like with it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "colab_type": "code", "executionInfo": { "elapsed": 206, "status": "ok", "timestamp": 1548171367373, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "qNiFzqD5mUpK", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" }, "outputId": "476db0b0-a9a3-46ae-8a23-be7e949d7858" }, "outputs": [], "source": [ "answer = two_by_two_solver(a1 = 4.5, b1 = 3, a2 = 1.5, \n", " b2 = 3, c1 = 10.5, c2 = 7.5)\n", "x = answer[0] #store in the variable x the first value in the list answer\n", "y = answer[1] #store in the variable y the first value in the list answer\n", "print(\"The list\",answer,\"contains\",x,\"and\",y)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "
\n", "Home Activity: Solve the linear system given below and store the answers in `my_x` and `my_y`. This will be auto-graded.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "$$ 2 x -1 y = 3\\\\ -4 x + 3 y = 0.$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "outputs": [], "source": [ "# YOUR SOLUTION HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbgrader": { "grade": true, "grade_id": "linear-system", "locked": true, "points": "0.25", "solution": false }, "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "sFrdpv13mUpN", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "We can do even fancier things, if we are so bold" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 52 }, "colab_type": "code", "executionInfo": { "elapsed": 211, "status": "ok", "timestamp": 1548171409505, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "CJnRIB0EmUpO", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" }, "outputId": "9052ec88-8026-4818-d91e-070aadb8ea84" }, "outputs": [], "source": [ "#just get x\n", "x = two_by_two_solver(a1 = 4.5, b1 = 3, a2 = 1.5, \n", " b2 = 3, c1 = 10.5, c2 = 7.5)[0]\n", "print(\"x =\",x)\n", "\n", "#assign variables to the output on the fly\n", "x,y = two_by_two_solver(a1 = 4.5, b1 = 3, a2 = 1.5, \n", " b2 = 3, c1 = 10.5, c2 = 7.5)\n", "print(\"x =\",x,\"y =\",y)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "62Uy2NQAmUpS", "nbpages": { "level": 3, "link": "[1.4.2.2 Return Values](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.2-Return-Values)", "section": "1.4.2.2 Return Values" } }, "source": [ "These examples are more advanced and they are designed to show you some of the neat tricks you can do in python." ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "oI3rB4rLmUpT", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" } }, "source": [ "### 1.4.2.3 Docstrings and Help" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "W4ylc7JWmUpU", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" } }, "source": [ "Our 2x2 solver code had a long, and pretty detailed comment at the beginning of it. This is called a **docstring** and it is printed by a user by typing" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 347 }, "colab_type": "code", "executionInfo": { "elapsed": 361, "status": "ok", "timestamp": 1548171434571, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "0xGhyjKCmUpW", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" }, "outputId": "8774e128-27fa-44e9-f197-aa2e1bf7305f" }, "outputs": [], "source": [ "help(two_by_two_solver)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "lAJ6D9_UmUpZ", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" } }, "source": [ "The point of this long comment is to communicate to other people:\n", "1. The main idea behind the function.\n", "2. What the function expects from you. **Inputs.**\n", "3. What the function gives you. **Outputs.** \n", "\n", "In this example we can see that we need to provide at least 6 numbers, and possibly an optional boolean. \n", "\n", "It is good programming practice to include good docstrings. It will be mandatory for any code you turn in this class.\n", "\n", "Let's look at the docstring for some members of the math module and the random module." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 139 }, "colab_type": "code", "executionInfo": { "elapsed": 203, "status": "ok", "timestamp": 1548171517726, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "N-EncpsVmUpa", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" }, "outputId": "e329331e-658f-40f9-87ee-c68202fbb28e" }, "outputs": [], "source": [ "import math\n", "help(math.fabs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 104 }, "colab_type": "code", "executionInfo": { "elapsed": 204, "status": "ok", "timestamp": 1548171525345, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "-LMJYruXmUpc", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" }, "outputId": "37d7bf12-71ce-406d-d695-ce00462473c7" }, "outputs": [], "source": [ "import random\n", "help(random.uniform)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "AjG89EI9mUpe", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" } }, "source": [ "We don't have the source code for these functions in front of us, but if we want to know how to call them (and we didn't want to Google® them), the docstrings tell us what to do.\n", "\n", "You may wonder why those docstrings are a bit different that the one I used. The format for mine is derived from the Google coding standards for python docstrings." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 87 }, "colab_type": "code", "executionInfo": { "elapsed": 336, "status": "ok", "timestamp": 1548171541881, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "JrJGqh2PmUpf", "nbpages": { "level": 3, "link": "[1.4.2.3 Docstrings and Help](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.2.3-Docstrings-and-Help)", "section": "1.4.2.3 Docstrings and Help" }, "outputId": "df4b7b99-0d26-44a6-dbc5-d00f8f0b2ada" }, "outputs": [], "source": [ "def nothing():\n", " #this function does nothing\n", " #docstring?\n", " return 0\n", "help(nothing)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "05U9SxiumUpi", "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "## 1.4.3 Scope" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "VMozxvm3mUpi", "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "When we call a function, it carves out in the computer's memory its own space. Variables that live in the special space, known as *local scope* are completely different than those in other parts of the program. Here's a simple, but illustrative example:" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "
\n", "Home Activity: Before you run the code below, predict the output. This is good practice for exam questions, where you'll be asked to predict the output of Python code without access to a computer.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "**Home Activity - Your Predictions**\n", "\n", "`x = `\n", "\n", "`new_x = `\n", "\n", "`y = `\n", "\n", "`new_y = `" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 87 }, "colab_type": "code", "executionInfo": { "elapsed": 208, "status": "ok", "timestamp": 1548171670147, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "6ib67kwkmUpk", "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" }, "outputId": "92105613-a2c6-42bc-cbf3-4d660496cd58" }, "outputs": [], "source": [ "def scope_demonstration(input_variable):\n", " ''' A simple demonstration of scoping rules\n", " \n", " Args:\n", " input_variable: a string or number\n", " \n", " Returns:\n", " x: --REDACTED TO NOT GIVE AWAY THE ACTIVITY ANSWER --\n", " '''\n", " x = input_variable*3\n", " return x\n", "\n", "#now call the function after defining some variables\n", "x = \"oui \"\n", "y = \"no \"\n", "\n", "new_x = scope_demonstration(x)\n", "new_y = scope_demonstration(y)\n", "print(\"x =\",x,\"\\nnew_x =\",new_x)\n", "print(\"y =\",y,\"\\nnew_y =\",new_y)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "koE8_zbcmUpm", "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "When I call scope_demonstration it creates its own memory space and any variable I create in there is different than in the rest of the program, even if the variables have the same name.\n", "\n", "There are many subleties in scoping rules, but this example outlines just about everything that you'll need to know as a neophyte programmer." ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "A variable declared at the top level Python file, i.e., outside a function, is in the global scope for that file. This is easiest to see in an example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "outputs": [], "source": [ "my_var = 1\n", "\n", "def print_my_var():\n", " ''' Another scope demonstration\n", " \n", " Args:\n", " Nothing\n", " \n", " Returns:\n", " Nothing\n", " \n", " Other:\n", " prints `my_var`\n", " \n", " '''\n", " print(my_var)\n", " return None\n", "\n", "print_my_var()" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "We were able to access `my_var` inside the function even though it was not an input to a function.\n", "\n", "The next natural guess is can we modify `my_var` with a function? Let's see." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "outputs": [], "source": [ "def change_my_var():\n", " ''' A third scope demonstration\n", " \n", " Args:\n", " Nothing\n", " \n", " Returns:\n", " Nothing\n", " \n", " Other:\n", " Attempts to change `my_var, prints to screen\n", " '''\n", " \n", " my_var = 3*my_var + 2\n", " print(\"my_var = \",my_var,\" inside the function\")\n", " \n", " return None\n", "\n", "change_my_var()\n", "print(\"my_var =\",my_var,\" outside the function\")" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "We got an error message! In Python, we can only access `my_var` inside functions. We cannot change it inside functions. If we wanted to change my_var, we would need to do the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "outputs": [], "source": [ "def change_my_var2():\n", " ''' A third scope demonstration\n", " \n", " Args:\n", " Nothing\n", " \n", " Returns:\n", " New value of my_var\n", " \n", " '''\n", " \n", " return 3*my_var + 2\n", "\n", "my_var = change_my_var2()\n", "print(\"Now my_var =\",my_var)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "
\n", "Class Activity: Take 30 seconds to predict the output of the code below without running it. Below are multiple choice answers.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "outputs": [], "source": [ "def my_func1(x,y):\n", " ''' A simple function to demonstrate the nuances of scope\n", "\n", " Arguments:\n", " x: scalar real number\n", " y: scalar real number\n", " \n", " Returns:\n", " z: scalar real number\n", "\n", " '''\n", " z = x + y\n", " x = 3\n", " y = z - x + 1\n", " return z\n", "\n", "# Run the function\n", "x = 1\n", "y = 1\n", "z = my_func1(x,y)\n", "# Print values of x, y, and z to screen\n", "print(\"x =\",x,\" y =\",y,\" z =\",z)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "source": [ "**Class Activity multiple choice answers**:\n", "1. x=1, y=1, z=2\n", "2. x=1, y=1, z=3\n", "3. x=3, y=0, z=2\n", "4. x=3, y=0, x=3\n", "5. None of these" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[1.4.3 Scope](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.3-Scope)", "section": "1.4.3 Scope" } }, "outputs": [], "source": [ "### Create your answer here." ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "-3eYjGzVmUpn", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "## 1.4.4 Recursion" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "jIx-g2LXmUpo", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "The idea behind recursion is that a function can call itself. That is really it. That capability can allow some neat tricks, but in practice there is often a faster way of doing things than using recursion.\n", "\n", "
\n", " Home Activity: Write pseudcode to calculate the factorial of integer x two ways: i) without recursion and ii) with recursion. Submit your pseudocode via Gradescope. We'll only assess for completeness (making an attempt, following guidelines) and not accuracy. Be sure to bring your pseudocode to class.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "
\n", "Class Activity: Explain your pseudocode to a partner. One person explains without recursion and the other explains with recurison.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "Below are two functions that calculate factorial with and without recurision." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 69 }, "colab_type": "code", "executionInfo": { "elapsed": 6407, "status": "ok", "timestamp": 1548341886692, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "xPp7tbeZmUpp", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" }, "outputId": "90f914fb-2e29-4657-f752-3947d9054036" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter an integer: 212\n", "212 ! = 4733702182912325971198157282773458528972111665671644583063162654840567216299326200333597974632020795344694044141162288574741860330707871653991802372413420954892019572846468089404909755852192508097446724647826768577878987213960691804730882223315446309650598202756704313010742315578131345078364709758529795655446581758477730600169824143256656411069775872000000000000000000000000000000000000000000000000000\n", "212 ! = 4733702182912325971198157282773458528972111665671644583063162654840567216299326200333597974632020795344694044141162288574741860330707871653991802372413420954892019572846468089404909755852192508097446724647826768577878987213960691804730882223315446309650598202756704313010742315578131345078364709758529795655446581758477730600169824143256656411069775872000000000000000000000000000000000000000000000000000\n" ] } ], "source": [ "def factorial(n, prev=1):\n", " if not((n==1) or (n==0)):\n", " prev = factorial(n-1,prev)*n\n", " return prev\n", "\n", "def factorial_no_recursion(n):\n", " output = 1;\n", " #can skip 1 because x*1 = 1\n", " for i in range(2,n+1):\n", " output = output*i\n", " return output\n", "x = int(input(\"Enter an integer: \"))\n", "print(x,\"! =\",factorial(x))\n", "print(x,\"! =\",factorial_no_recursion(x))" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "jNPXf9AmmUpr", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "Let's see which is faster. This will use some ipython magic commands for timing execution. We'll compute the factorials of 0 through 20, 100,000 times." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 52 }, "colab_type": "code", "executionInfo": { "elapsed": 5696, "status": "ok", "timestamp": 1548342028336, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "ZDJcHnxSmUps", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" }, "outputId": "fa9a9323-3e4a-40ba-b921-ac70399ccdc8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 3.19 s, sys: 26.5 ms, total: 3.22 s\n", "Wall time: 3.22 s\n" ] } ], "source": [ "%%time\n", "for times in range(10**5):\n", " for n in range(21):\n", " factorial(n)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 52 }, "colab_type": "code", "executionInfo": { "elapsed": 2461, "status": "ok", "timestamp": 1548342021383, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "JsIooy9SmUpu", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" }, "outputId": "73da1d63-8e06-4d80-bfab-6ff22054ebe4" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 1.38 s, sys: 12 ms, total: 1.39 s\n", "Wall time: 1.39 s\n" ] } ], "source": [ "%%time\n", "for times in range(10**5):\n", " for n in range(21):\n", " factorial_no_recursion(n)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "l6W2nscSmUpw", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "*Side-tangent*: wall versus CPU user versus CPU clock time:\n", "https://stackoverflow.com/questions/7335920/what-specifically-are-wall-clock-time-user-cpu-time-and-system-cpu-time-in-uni\n", "(Side-tangents will not appear in tests or assignments, but are given to satisfy your curiosity.)\n", "\n", "\n", "The no recursion version, while not as neat, is nearly 50% faster. It is also possible to have too many levels of recursion." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 478 }, "colab_type": "code", "executionInfo": { "elapsed": 3818, "status": "error", "timestamp": 1548342081893, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "0EI-GBjNmUpx", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" }, "outputId": "c58e705f-fe78-4e1b-cffc-88449630a23a" }, "outputs": [ { "ename": "RecursionError", "evalue": "maximum recursion depth exceeded in comparison", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m#this won't work and prints ~1000 errors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m#the errors are not repeated here\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\"! =\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, prev)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprev\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprev\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mprev\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mprev\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "... last 1 frames repeated, from the frame below ...\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, prev)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprev\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprev\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mprev\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mprev\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded in comparison" ] } ], "source": [ "import sys\n", "sys.setrecursionlimit(1000) # change this to answer the home activity question\n", "x = 1000\n", "#this won't work and prints ~1000 errors\n", "#the errors are not repeated here\n", "print(x,\"! =\",factorial(x))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "
\n", "Home Activity: What is the smallest recursion limit for which factorial(1000) works?\n", "
" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 55 }, "colab_type": "code", "executionInfo": { "elapsed": 212, "status": "ok", "timestamp": 1548342102565, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "QI4oXlKYmUp0", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" }, "outputId": "4131853e-c431-47de-f092-bd387e56958f" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000 ! = 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n" ] } ], "source": [ "x = 1000\n", "#this works\n", "answer = factorial_no_recursion(x)\n", "print(x,\"! =\",answer)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "1OTTybGrmUp5", "nbpages": { "level": 2, "link": "[1.4.4 Recursion](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.4-Recursion)", "section": "1.4.4 Recursion" } }, "source": [ "By the way, I'm surprised it is giving the correct answer." ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "TyQ2GN3QmUp9", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" } }, "source": [ "## 1.4.5 Modules" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "XkaByqoPmUp9", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" } }, "source": [ "Sometimes we have to define many functions and don't want to have one giant source file (in fact this is good programming practice). I've created a file called sphere.py in the same directory as this notebook. This file defines two functions volume and surface_area that compute the volume and surface area of a sphere. Because the file is called sphere.py we can import those functions using import sphere. The text of sphere.py is\n", "\n", "def volume(radius):\n", " \"\"\"compute volume of a sphere\n", "\n", " Args:\n", " radius: float giving the radius of the sphere\n", "\n", " Returns:\n", " volume of the sphere as a float\n", " \"\"\"\n", " return 4.0/3.0*math.pi*radius**3\n", "\n", "def surface_area(radius):\n", " \"\"\"compute surface area of a sphere\n", "\n", " Args:\n", " radius: float giving the radius of the sphere\n", "\n", " Returns:\n", " surface area of the sphere as a float\n", " \"\"\"\n", " return 4.0*math.pi*radius**2\n", "" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "tlLecRQrmUp-", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" } }, "source": [ "I can use the help function to tell me about the module:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 305 }, "colab_type": "code", "executionInfo": { "elapsed": 214, "status": "error", "timestamp": 1548342630031, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "vLceeHInmUp-", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" }, "outputId": "4523bd79-84b2-4676-b141-ee0478b99e47" }, "outputs": [ { "ename": "ModuleNotFoundError", "evalue": "No module named 'sphere'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mModuleNotFoundError\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;32mimport\u001b[0m \u001b[0msphere\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'sphere'" ] } ], "source": [ "import sphere" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "bHY2QBP-mUqE", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" } }, "source": [ "Now that I have imported the module, we can can the ``help`` to see the docstring." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 503 }, "colab_type": "code", "executionInfo": { "elapsed": 947, "status": "ok", "timestamp": 1548342704255, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "uwNBZ_qDw7dg", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" }, "outputId": "8bee4987-07da-4cec-f137-39160597e428" }, "outputs": [], "source": [ "help(sphere)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 357 }, "colab_type": "code", "executionInfo": { "elapsed": 218, "status": "error", "timestamp": 1548343066948, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "yLMMJ1K2mUqE", "nbpages": { "level": 2, "link": "[1.4.5 Modules](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.5-Modules)", "section": "1.4.5 Modules" }, "outputId": "71322f84-008e-4383-fc77-4475e096a453" }, "outputs": [], "source": [ "r = 1.0\n", "print(\"The volume of a sphere of radius\",r,\"cm is\",\n", " sphere.volume(r),\"cm**3\")\n", "print(\"The surface area of a sphere of radius\",r,\"cm is\",\n", " sphere.surface_area(r),\"cm**2\")" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "dIlyNiOlmUqL", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "## 1.4.6 Files" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "AAXEv6KhmUqL", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "It is very easy to read in text files in python. The file fifth_republic.txt, lists the presidents of France's fifth republic. It is in the same folder as this notebook." ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "SfdodJFxAMQk", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "In Python, we can read it in very simply:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 156 }, "colab_type": "code", "executionInfo": { "elapsed": 218, "status": "ok", "timestamp": 1548342816789, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "ATuVx4zCmUqM", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" }, "outputId": "56d032d8-dd47-4012-ae09-1de8a9a26d01" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CharlCharlCharl\n", "GeorgGeorgGeorg\n", "ValérValérValér\n", "FrançFrançFranç\n", "JacquJacquJacqu\n", "NicolNicolNicol\n", "FrançFrançFranç\n", "EmmanEmmanEmman\n" ] } ], "source": [ "file = open('./data/fifth_republic.txt', 'r') \n", "#open fifth_republic.txt for reading ('r')\n", "for line in file:\n", " # Repeat the first 5 characters 3 times\n", " print(line[0:5]*3)\n", "file.close()" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "BAQsK1rmmUqQ", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "Notice how the for loop can iterate through each line of the file. You can also read a line at a time." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 87 }, "colab_type": "code", "executionInfo": { "elapsed": 197, "status": "ok", "timestamp": 1548342842273, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "f4YvuXmvmUqQ", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" }, "outputId": "8ea2fdff-7c95-49cb-ac7e-9a863a3a9838" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Charles de Gaulle\n", "\n", "Georges Pompidou\n", "\n" ] } ], "source": [ "file = open('./data/fifth_republic.txt', 'r')\n", "#open fifth_republic.txt for reading ('r')\n", "\n", "# Read the first line\n", "first_line = file.readline()\n", "\n", "# Read the second line\n", "second_line = file.readline()\n", "print(first_line)\n", "print(second_line)\n", "file.close()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 139 }, "colab_type": "code", "executionInfo": { "elapsed": 354, "status": "ok", "timestamp": 1548342846065, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "v8xsw-EWmUqR", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" }, "outputId": "cd8058ba-1d3d-4431-ae97-bc2f8d34715f" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function readline:\n", "\n", "readline(size=-1, /) method of _io.TextIOWrapper instance\n", " Read until newline or EOF.\n", " \n", " Returns an empty string if EOF is hit immediately.\n", "\n" ] } ], "source": [ "help(file.readline)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "vMAp1wpDmUqS", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "You can also easily write to a file. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 260 }, "colab_type": "code", "executionInfo": { "elapsed": 365, "status": "ok", "timestamp": 1548342885980, "user": { "displayName": "Alexander Dowling", "photoUrl": "https://lh3.googleusercontent.com/-LChdQ2m5OQE/AAAAAAAAAAI/AAAAAAAAAA0/JeXJe4vQJ7M/s64/photo.jpg", "userId": "00988067626794866502" }, "user_tz": 300 }, "id": "s31YtusPmUqT", "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" }, "outputId": "f99dbc1e-e899-4d36-9790-4b28648f64d0" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fedora\n", "\n", "trilby\n", "\n", "porkpie\n", "\n", "tam o'shanter\n", "\n", "Phrygian cap\n", "\n", "Beefeaters' hat\n", "\n", "sombrero\n", "\n" ] } ], "source": [ "writeFile = open(\"./data/hats.txt\",\"w\") \n", "#open hats.txt to write (clobber if it exists)\n", "hats = [\"fedora\",\"trilby\",\"porkpie\",\n", " \"tam o'shanter\",\"Phrygian cap\",\"Beefeaters' hat\",\"sombrero\"]\n", "for hat in hats:\n", " writeFile.write(hat + \"\\n\") #add the endline\n", "writeFile.close()\n", "\n", "#now open file and print\n", "readFile = open(\"./data/hats.txt\",\"r\")\n", "for line in readFile:\n", " print(line)\n", "readFile.close()" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "source": [ "We can also use `enumerate` with a text file:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "nbpages": { "level": 2, "link": "[1.4.6 Files](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.6-Files)", "section": "1.4.6 Files" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Charles de Gaulle\n", "\n", "Georges Pompidou\n", "\n", "Valéry Giscard d'Estaing\n", "\n", "François Mitterrand\n", "\n", "Jacques Chirac\n", "\n", "Nicolas Sarkozy\n", "\n", "François Hollande\n", "\n", "Emmanuel Macron\n" ] } ], "source": [ "import csv\n", "file = open('./data/fifth_republic.txt', 'r')\n", "for i,row in enumerate(file):\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[1.4.7 Example: High/Low Guess My Number Game](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7-Example:-High/Low-Guess-My-Number-Game)", "section": "1.4.7 Example: High/Low Guess My Number Game" } }, "source": [ "## 1.4.7 Example: High/Low Guess My Number Game" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.1 Instructions](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.1-Instructions)", "section": "1.4.7.1 Instructions" } }, "source": [ "### 1.4.7.1 Instructions\n", "\n", "Write pseudocode and Python function program to interactively play the following game:\n", "1. Generate a random integer number between 0 and 100.\n", "2. Ask the player to guess a number. Capture their input from the keyboard.\n", "3. Check if the number is valid (between 0 and 100, integer). If not, warn the player and\n", "goto Step 2.\n", "4. If the player’s guess is correct, they win. Print out “Congratulations” and tell them\n", "how many guesses it took. Only count valid guesses. Terminate the program.\n", "5. If the guess is too low, print “Guess is too low.” and goto Step 2.\n", "6. If the guess is too high, print “Guess is too high.” and goto Step 2.\n", "\n", "First write the pseudocode and then implement as a function in Python. Test your program at least 2 times." ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.2 Pseudocode](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.2-Pseudocode)", "section": "1.4.7.2 Pseudocode" } }, "source": [ "### 1.4.7.2 Pseudocode" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.3 Python Implementation](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.3-Python-Implementation)", "section": "1.4.7.3 Python Implementation" } }, "source": [ "### 1.4.7.3 Python Implementation" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.3 Python Implementation](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.3-Python-Implementation)", "section": "1.4.7.3 Python Implementation" } }, "outputs": [], "source": [ "# import libraries\n", "import numpy as np\n", "\n", "# function to accept guess from user and determine if guess matches secret \n", "# number between 0 and 100\n", "def guessing_game(rand_num=None):\n", " ''' Play the guess my number interactively with keyboard input\n", " \n", " Argument:\n", " rand_num: the random (secret) number. If None (default), the program generates\n", " a random integer between 0 and 100.\n", " \n", " Returns:\n", " Nothing\n", " \n", " Other:\n", " Asks user for interactive keyboard input that are integers\n", " \n", " '''\n", " \n", " # YOUR SOLUTION HERE" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "source": [ "### 1.4.7.4 Testing" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "source": [ "**Test 1**: No input. The function will automatically generate a secret number." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Guess the number: 51\n", "Guess is too high\n", "\n", "Guess the number: 25\n", "Guess is too high\n", "\n", "Guess the number: 10\n", "Guess is too low\n", "\n", "Guess the number: 15\n", "Guess is too low\n", "\n", "Guess the number: 20\n", "Guess is too low\n", "\n", "Guess the number: 22\n", "Guess is too high\n", "\n", "Guess the number: 21\n", "\n", "Congratulations! Your guess is correct. Number is: 21\n", "Number of guesses: 7\n" ] } ], "source": [ "# YOUR SOLUTION HERE" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "source": [ "**Test 2**: What happens if we supply an out-of-bounds (invalid) secret number?" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Secret number if too small.\n" ] } ], "source": [ "# YOUR SOLUTION HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 3, "link": "[1.4.7.4 Testing](https://ndcbe.github.io/cbe-xx258/01.04-Functions-scoping.html#1.4.7.4-Testing)", "section": "1.4.7.4 Testing" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [1.3 Flow Control and Pseudocode](https://ndcbe.github.io/cbe-xx258/01.03-Flow-control.html) | [Contents](toc.html) | [1.5 List, Dictionaries, and Enumeration](https://ndcbe.github.io/cbe-xx258/01.05-Lists-Dictionaries-Enumerate.html) >

\"Open

\"Download\"" ] } ], "metadata": { "colab": { "name": "L3-Functions-Scoping-Etc.ipynb", "provenance": [], "version": "0.3.2" }, "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.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }