7 "name": "03-Python-modules.ipynb",
9 "collapsed_sections": []
12 "display_name": "Python 3",
21 "file_extension": ".py",
22 "mimetype": "text/x-python",
24 "nbconvert_exporter": "python",
25 "pygments_lexer": "ipython3",
31 "cell_type": "markdown",
36 "# Python Tutorial III: Modules\n",
37 "In this lecture, we will see how to make code more organized by creating user-defined modules and split the code into multiple reusable parts."
41 "cell_type": "markdown",
50 "* A file containing Python definitions and statements.\n",
51 "* The file name is the module name with the suffix .py appended.\n",
52 "* Within a module, the module's name is available as the valuable of the global variable *__name__*.\n",
55 "* Your script gets very long and you want to have easier maintenance. \n",
56 "* You want to reuse a function in several programs or scripts without copy/paste.\n",
57 "* Performance reasons.\n",
59 "Let's look at an example:\n",
61 "Let's get file ``differences.py`` "
70 "# copy from github raw url if we do not have the file already\n",
72 "if not os.path.exists('differences.py'):\n",
73 " use the shell escale ! to run the command wget and copy the file at https://raw.githubusercontent.com/janmandel/CCM-Intro-to-SC/main/differences.py to your runtime contents\n",
75 " print('file already exists')\n",
79 "execution_count": null,
89 "import differences as diff # We import the module just like we import numpy\n",
90 "print('if we got here the import went OK')\n"
92 "execution_count": null,
101 "# magic to make the output appear here https://pythonguides.com/what-is-matplotlib-inline/\n",
102 "%matplotlib inline \n",
104 "import matplotlib.pyplot as plt\n",
105 "import numpy as np\n",
107 "# code a functkon and its derivative\n",
109 " return np.exp(-x**2)*np.sin(np.pi*x)\n",
112 " return np.exp(-x**2)*(np.pi*np.cos(np.pi*x)-2*x*np.sin(np.pi*x))\n"
114 "execution_count": null,
123 "# make a figure number 0\n",
125 "plt.plot(x,myfun(x))\n",
126 "plt.title('$f(x) = e^{-x^2}\\sin(\\pi x)$')"
128 "execution_count": null,
137 "# now compute numerical derivatives \n",
139 "# make mesh of points on x axis\n",
140 "x = np.linspace(0,1,100) \n",
142 "fprime_FD = diff.for_diff(myfun,x,.1) #array of forward difference approximation to the derivative\n",
144 "# remember the figure objects as variable\n",
145 "fig1 = plt.figure(1, figsize=(15, 6)) # for plots of forward difference approx\n",
147 "axes1_1 = fig1.add_subplot(1, 2, 1) #the first plot in a 1x2 array\n",
148 "axes2_1 = fig1.add_subplot(1, 2, 2) #the second plot in a 1x2 array\n",
150 "axes1_1.plot(x,myder(x),label='$f^\\prime$')\n",
151 "axes1_1.plot(x,fprime_FD,label='FD approx of $f^\\prime$')\n",
152 "axes1_1.legend(loc='upper right', fontsize=14)\n",
154 "axes2_1.plot(x,myder(x)-fprime_FD)\n",
155 "axes2_1.set_title('Error in the approximate forward derivative')\n"
157 "execution_count": null,
166 "# compute and plot the same for backward difference approximation to the derivative\n",
167 "# use new variables for the figure and axes, do not reuse\n",
168 "# can reuse array x\n",
169 "fig2 = plt.figure(2, figsize=(15, 6)) # for plots of backward difference approx\n",
171 "fprime_BD = diff.back_diff(myfun,x,.1) #backward difference approximation to the derivative\n",
172 "axes1_1b = fig2.add_subplot(1, 2, 1) #the first plot in a 1x2 array\n",
173 "axes2_1b = fig2.add_subplot(1, 2, 2) #the second plot in a 1x2 array\n",
175 "axes1_1b.plot(x,myder(x),label='$f^\\prime$')\n",
176 "axes1_1b.plot(x,fprime_BD,label='BD approx of $f^\\prime$')\n",
177 "axes1_1b.legend(loc='upper right', fontsize=14)\n",
179 "axes2_1b.plot(x,myder(x)-fprime_BD)\n",
180 "axes2_1b.set_title('Error in the approximate backward derivative')\n",
183 "execution_count": null,
192 "# compute and plot the same for central difference approximation to the derivative\n",
193 "# use new variable for the figure, do not reuse\n",
194 "# can reuse array x\n",
197 "execution_count": null,
201 "cell_type": "markdown",
206 "## Look at the pictures and print below which numerical derivative is most accurate: forward, backward, or central?## "
217 "execution_count": null,
221 "cell_type": "markdown",
227 "## Where does a module file need to go?\n",
229 "Say you are trying to `import spam`.\n",
231 "When importing, the interpreter searches for spam in locations in the list of directories given by the variable *sys.path*.\n",
232 "On Colab, this includes the directory /contents, which is your running directory.\n",
237 "cell_type": "markdown",
242 "##Exercise: import the package sys and print the variable sys.path"
253 "execution_count": null,
257 "cell_type": "markdown",
262 "## Generalizations of Modules: Packages\n",
264 "Packages (i.e., libraries) are modules with a *directory* structure.\n",
265 "You can even make packages with subpackages and simply exploit the dot.dot reference to navigate through the package to get to the function you want (e.g. matplotlib.pyplot.plot). \n",
266 "If you want to develop a well-comparmentalized package you can look at online help: https://python-packaging.readthedocs.io/en/latest/"