diff options
| author | pants <niklasjo2004@gmail.com> | 2026-09-21 14:17:45 -0700 |
|---|---|---|
| committer | pants <niklasjo2004@gmail.com> | 2026-09-21 14:17:45 -0700 |
| commit | a33d49ac4d1ce554c72770927957a089b4023bf1 (patch) | |
| tree | 17ea036b5a0e8b488dc236f0ce48a275ecd80ef8 /python/atms-310/notebooks/Week 03 M.ipynb | |
Diffstat (limited to 'python/atms-310/notebooks/Week 03 M.ipynb')
| -rwxr-xr-x | python/atms-310/notebooks/Week 03 M.ipynb | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/python/atms-310/notebooks/Week 03 M.ipynb b/python/atms-310/notebooks/Week 03 M.ipynb new file mode 100755 index 0000000..f68849f --- /dev/null +++ b/python/atms-310/notebooks/Week 03 M.ipynb @@ -0,0 +1,335 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h1>5. Modules and Exception Handling</h1>\n", + "<h2>10/09/2023</h2>" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h2>5.0 Last Time...</h2>\n", + "\n", + "<ul>\n", + " <li>A <b>for loop</b> lets you repeat an operation a specified number of times.</li>\n", + " <li>Indentation is critical for loops in Python.</li>\n", + " <li>The range() function will create a list of all values up to the specified integer.</li>\n", + " <li>Hardcoding is the act of (often unnecessarily) restricting a piece of code so it only works under specific circumstances.</li>\n", + " <li>A <b>while loop</b> lets you repeat an operation until a particular condition is met.</li>\n", + " <li>The index in a while loop must be initialized and care should be taken to avoid infinite loops.</li>\n", + "</ul>" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h2>5.1 Modules</h2>\n", + "\n", + "A <b>module</b> is just a library of Python source code files that will give you access to new (frequently more specialized) functions.\n", + "\n", + "To import a module, the syntax is simply: <b>import \\<module name\\></b>." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-0.7568024953079283\n" + ] + } + ], + "source": [ + "# An extremely useful module in the atmospheric science world is NumPy.\n", + "# This package lets you use a variety of mathematical (and array-based) functions and variables.\n", + "import numpy\n", + "\n", + "\n", + "# As soon as the module is imported, you have access to all its contents.\n", + "\n", + "# To refer to a function or variable within numpy, just follow it with a \n", + "# period, then the function or variable in question.\n", + "\n", + "# As an example, numpy will let you calculate the sine of a given number.\n", + "a = numpy.sin(4)\n", + "print(a)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some modules have what are called <b>submodules</b> that can be referred to in a similar way. For instance, the module NumPy has a submodule called ma, which in turn has particular functions defined within it. If you wanted to run the <b>array</b> function inside the <b>ma</b> submodule inside the <b>NumPy</b> module, it would look like <b>numpy.ma.array</b>.\n", + "\n", + "Modules have detailed documentation (typically easily found via Google) that will let you browse all the available functions at your disposal. This instance of Jupyter has several modules preinstalled; they may be missing if you try running them on a Python build at home. Fortunately, there are generally helpful instructions online for downloading new modules so they can be imported into your code." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.7568024953079282" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# If you find yourself typing the same module name again and again, \n", + "# you can rename it to something a little quicker!\n", + "\n", + "import numpy as np\n", + "\n", + "a = np.sin(4)\n", + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a meteorological example, let's return to our list of Celsius temperatures from yesterday. NumPy will enable us to easily calculate the maximum and minimum temperatures." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The maximum temperature is 36.5 and the minimum temperature is 13.5.\n" + ] + } + ], + "source": [ + "# First, here's our temperature list.\n", + "\n", + "temp = [23.5,24.5,18.0,26.8,17.7,17.0,27.1,24.6,13.5,36.5]\n", + "\n", + "# Let's import NumPy.\n", + "\n", + "import numpy as np\n", + "\n", + "# Now, use the max() and min() functions within the NumPy module\n", + "# to calculate the maximum and minimum temperatures.\n", + "\n", + "maxT = np.max(temp)\n", + "minT = np.min(temp)\n", + "\n", + "# We can even output a nice sentence summing it up!\n", + "\n", + "print(\"The maximum temperature is \"+str(maxT)+\" and the minimum temperature is \"+str(minT)+\".\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<b>An example!</b>\n", + "\n", + "In the box below, write a block of code that will apply a NumPy mathematical function of your choice to the list of temperatures <b>(temp)</b> above: https://numpy.org/doc/stable/reference/routines.math.html. Don't forget to include your module import statement!" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-0.99808203 -0.59135753 -0.75098725 0.9953511 -0.91258245 -0.96139749\n", + " 0.92243282 -0.50789659 0.80378443 -0.93171689]\n", + "[-0.06190529 0.80640949 0.66031671 -0.09631292 0.40889274 -0.27516334\n", + " -0.38615761 0.86141805 0.59492066 0.36318541]\n", + "[ 16.12272495 -0.73332164 -1.13731371 -10.33455467 -2.23183823\n", + " 3.49391565 -2.38874697 -0.58960523 1.35107835 -2.56540287]\n" + ] + } + ], + "source": [ + "temp = [23.5,24.5,18.0,26.8,17.7,17.0,27.1,24.6,13.5,36.5]\n", + "import numpy as np\n", + "\n", + "# Mathematical function #1.\n", + "print(np.sin(temp))\n", + "\n", + "# Mathematical function #2.\n", + "print(np.cos(temp))\n", + "print(np.tan(temp))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h2>5.2 Exception Handling</h2>\n", + "\n", + "An \"exception\" is a very polite way of saying \"error\" in programming-speak. Often we use an if statement to determine whether something is going to cause a problem, and then use a <b>raise</b> statement to tell the code to stop and output a particular error." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n", + "12.566370614359172\n" + ] + } + ], + "source": [ + "# Let's say we have a code that will attempt to calculate the area of a circle\n", + "# based on its radius.\n", + "# It works well for positive values of radius, but we want to allow for the\n", + "# possibility that someone might enter a negative radius.\n", + "\n", + "import numpy as np\n", + "\n", + "def circle_area(radius):\n", + " if radius < 0:\n", + " raise ValueError('Radius cannot be negative, you fool!')\n", + " area = np.pi * (radius**2)\n", + " return area\n", + "\n", + "def quadarea(base, height):\n", + " if base < 0:\n", + " raise ValueError('enter a POSITIVE number')\n", + " elif height < 0:\n", + " raise ValueError('POSITIVE integer please')\n", + " x = base*height\n", + " return x\n", + "# Now try calling this function with a positive radius to make sure it works.\n", + "print(quadarea(2,3))\n", + "print(circle_area(2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Radius cannot be negative, you fool!", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[15], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Now try calling this function with a negative radius.\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mcircle_area\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m)\u001b[49m)\n", + "Cell \u001b[0;32mIn[14], line 10\u001b[0m, in \u001b[0;36mcircle_area\u001b[0;34m(radius)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcircle_area\u001b[39m(radius):\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m radius \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mRadius cannot be negative, you fool!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 11\u001b[0m area \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mpi \u001b[38;5;241m*\u001b[39m (radius\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m2\u001b[39m)\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m area\n", + "\u001b[0;31mValueError\u001b[0m: Radius cannot be negative, you fool!" + ] + } + ], + "source": [ + "# Now try calling this function with a negative radius.\n", + "\n", + "print(circle_area(-2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The syntax for <b>raise</b> is the exception class (for instance, ValueError() if a value is forbidden; this is the most common type of exception you'll have, but we'll see others as we go) followed by user-defined text that will give you more information about the error.\n", + "\n", + "Luckily, Python also lets you build in ways to deal with common exceptions if you're pretty sure you know where the user went wrong. For example, they may have accidentally put a negative sign on the radius, but you're pretty sure they just meant the positive value. In that case, you can use a <b>try/except</b> block, which will attempt to resolve the error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "28.274333882308138\n" + ] + } + ], + "source": [ + "# As an example, this code will call the area() function, and if it gets\n", + "# a ValueError exception, it'll try again with the absolute value\n", + "# of the range.\n", + "\n", + "radius = -3\n", + "try:\n", + " a = circle_area(radius)\n", + "except ValueError:\n", + " a = circle_area(abs(radius))\n", + " \n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h2>TAKE-HOME POINTS</h2>\n", + "\n", + "<ul>\n", + " <li>A <b>module</b> is a library of Python source code that gives access to new variables and functions.</li>\n", + " <li>Modules can be imported as whatever name you like.</li>\n", + " <li>A <b>raise</b> statement lets you define your own error conditions and stop code when they're met.</li>\n", + " <li>A <b>try/except</b> block will let you fix common issues that would otherwise result in exceptions.</li>\n", + "</ul>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# you can import modules with any name you want" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} |
