{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Python primer for HTMD" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "![](http://pub.htmd.org/tutorials/htmd_python_powered.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Why Python?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Modern, complete and open-source programming language\n", "* Wide spread throughout the scientific community\n", "* Easy to understand, rapid delivery and maintenance\n", "* C++ still wins on low latency and control of memory\n", " * However, Python is versatile and has packages that can be as fast as C (e.g. NumPy)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## HTMD relation to Python and Miniconda" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* HTMD is written in Python, using the **Python 3** synthax\n", "* HTMD is, and works as, a Python module.\n", "* HTMD is distributed through a package/module distribution platform called **Miniconda** (light-weight Anaconda)\n", "* _Advantages of Miniconda_:\n", " 1. Already distributes Python (`python`) and interactive Python (`ipython`) interpreters\n", " 1. Everything is self-contained inside Miniconda and one does not have to rely on the operative system" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Programming basics with Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Python can do pretty much what any other programming language can. Arithmetics, variable definition, printing, etc." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a is 5\n" ] } ], "source": [ "a = 3 + 2\n", "print('a is', a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Python Interpreters and writing Python code" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* `python` is the general interpreter\n", " * One can write a `script.py` file in Python and run `python script.py`\n", "* There are powerful ways of writing and prototyping code in Python:\n", " * Interactive interpreters (`ipython`, `jupyter`)\n", " * IDE's (Spyder, Pycharm)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Jupyter Notebooks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* This presentation is actually a Jupyter notebook (you can play with it, run the code yourself)\n", "* A notebook like this one is a grapical interactive environment.\n", "* It is made of cells:\n", " * **Text cells**, with formatted markdown text (like the bulleted text we have here)\n", " * **Code cells**, to run code interactively" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Extra: IPython built-in magic commands" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* In IPython, some [magic commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html) are available/built-in.\n", "* Useful to navigate the filesystem (% indicates a magic command)\n", "```python\n", "%ls\n", "%mkdir test\n", "```\n", "* Or for module reload for rewritting code for testing without need to reload the module all the time\n", "```python\n", "%load_ext autoreload\n", "%autoreload 2\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Python modules usage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* A Python module is a file containing Python definitions and statements.\n", "* In Python, modules have to be imported in order to be used.\n", "* Here we show two ways of importing modules and one way of importing a functionality:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "import os\n", "import numpy as np\n", "from glob import glob" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the first two, using the module funcionalities require the namespace: the original one `os`, or the defined one `np` (instead of `numpy`). In the last one, `glob` can be used instead of `glob.glob`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## `os` module and `glob` function: interacting with the filesystem" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* The `os` [module](https://docs.python.org/3/library/os.html) serves to interact with the operative system\n", "* Normal filesystem commands or magic commands work from the interactive session, but, in a program, the `os` functions should be used instead" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['python-primer.ipynb', 'python-primer.slides.html']" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.chdir('.') # change directory\n", "os.listdir('.') # list contents of directory\n", "glob('python-*') # returns pathnames matching a regex pattern" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## General Programming Overview" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Strings" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Strings are identified by single or double apices:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "b='newtest' \n", "c=\"newtest\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "### Relational operators" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Relational operators are `==`,`<`,`>`,`<=`,`>=`, and `!=`, and they can be connected with `and`,`or`,`not`" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b == c" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Lists of objects (integers, strings...)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Lists of different objects are created using square brackets" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ba\n" ] } ], "source": [ "d = [1, 2, 3, 'ba', 5, 6, 7, 8, 9]\n", "print(d[3])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Note:** in Python, indexes are zero-based." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Conditionals (_if-clause_)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100\n" ] } ], "source": [ "if 1 > 0:\n", " d = 100\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "As you probably know, in Python, **indentation** is important. Use indentation to define a scope of code after the `:`. `print(d)` is no longer inside the scope of the _if-clause_ because it is not indented." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Loops (_for-loop_)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n" ] } ], "source": [ "for i in [1,2,3,4,5]:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Another way of doing the same, using Numpy:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n" ] } ], "source": [ "for i in np.arange(1,6):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Numpy: the best way to handle arrays" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Arrays are best created and handled using `numpy` arrays (no need to import the module, we already did before)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 11. 12. 13. 14.]\n", " [ 21. 22. 23. 24.]\n", " [ 31. 32. 33. 34.]\n", " [ 41. 42. 43. 44.]]\n" ] } ], "source": [ "m = np.array([[ 11., 12, 13, 14 ],\n", " [ 21, 22, 23, 24 ],\n", " [ 31, 32, 33, 34 ],\n", " [ 41, 42, 43, 44 ]\n", " ]\n", " )\n", "print(m)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "where `m` is 4-by-4 matrix of double numbers (and not integers), due to the fact than `11.` is a real number (notice the dot)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Array multiplication" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Arrays can be multiplied easily element by element" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 33. 36. 39. 42.]\n", " [ 63. 66. 69. 72.]\n", " [ 93. 96. 99. 102.]\n", " [ 123. 126. 129. 132.]]\n" ] } ], "source": [ "n = 3.0 * m\n", "print(n)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A scalar multiplication is applied to each element of the array." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Sequences" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "An array sequence can be created with `arange` (like seen before). Array indexing starts at 0." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2 3]\n" ] } ], "source": [ "o = np.arange(0,4)\n", "print(o)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Slicing" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 2, 3])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "o[1:] #from 1 until the end, (starts at zero)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Note**: See how we got the outcome without printing? It's because we're in interactive Python" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 99., 32., 33., 34.],\n", " [ 99., 42., 43., 44.]])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:,0] = 99 # first column\n", "m[-2:,] # backwards indexing is possible, getting the last 2 rows" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### More matrix operations" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0., 12., 26., 42.],\n", " [ 0., 22., 46., 72.],\n", " [ 0., 32., 66., 102.],\n", " [ 0., 42., 86., 132.]])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.multiply(m,o)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 80., 140., 200., 260.])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.transpose()\n", "np.inner(m,o)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Other numpy operations" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 0, 1, 2, 3])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.concatenate((o,o))" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 396., 108., 112., 116.])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.sum(axis=0)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(4,)\n", "4\n", "1\n" ] } ], "source": [ "print(o.shape)\n", "print(o.size)\n", "print(o.ndim)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Functions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Subroutines are defined using `def`:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def test(a, b=1, c=3):\n", " return a*b*c" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test(1, c=5)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Variables and Objects" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* Python represents all its data as objects. \n", "* Variables are just names. \n", "* Some objects are mutable, some immutable.\n", " * Immutables are: int, float, complex, str, tuples, bytes, frozensets \n", " * Mutables are: list, byte array, sets, dict, classes" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Identity of an object" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "With ```id``` it is possible to check the unique identity of an object" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "140351964294272" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n = 1 # immutable integer\n", "id(n)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "140351964294304" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n += 1\n", "id(n) # new object" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "140351546176392" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = [1] # mutable list\n", "id(m)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "140351546176392" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.append(2)\n", "id(m) # same object" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Argument passing" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "* Passing an argument to a function is like creating a new name to the object\n", "* _If it is mutable_, then any change inside the function will affect the object outside. \n", "* _If it is immutable and the function changes it_, then python creates another object inside the function scope, so nothing changes outside of the function." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Plots using `matplotlib` module" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib.pylab import plot,title,xlabel,ylabel,grid,show,savefig,gcf\n", "#Optional: magic line to make plots inline\n", "%matplotlib inline\n", "\n", "x = np.arange(0,50,.5)\n", "y = np.sin(x/3) - np.cos(x/5)\n", "plot(x,y, '.-k')\n", "plot(x,np.sin(x/2) - np.cos(x/5),'.r')\n", "title('A simple double plot')\n", "xlabel('variable 1'), ylabel('variable 2'), grid(True)\n", "fig = gcf() # Get current figure\n", "show()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "The plot is shown inline, but can also be saved:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "fig.savefig('/tmp/foo.eps')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Getting Help" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "The `help` function provides help for any function:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function print in module builtins:\n", "\n", "print(...)\n", " print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n", " \n", " Prints the values to a stream, or to sys.stdout by default.\n", " Optional keyword arguments:\n", " file: a file-like object (stream); defaults to the current sys.stdout.\n", " sep: string inserted between values, default a space.\n", " end: string appended after the last value, default a newline.\n", " flush: whether to forcibly flush the stream.\n", "\n" ] } ], "source": [ "help(print)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Debugging code in notebooks" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Really nice to debug an error and see what's wrong by inspecting variables using `%debug` (Press PgDown for example)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'xxx' 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[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mxxx\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 3\u001b[0m \u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mbroken_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mc\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;36mbroken_function\u001b[0;34m(b)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mbroken_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mxxx\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[1;32m 3\u001b[0m \u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mbroken_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mNameError\u001b[0m: name 'xxx' is not defined" ] } ], "source": [ "def broken_function(b):\n", " print(b,xxx())\n", "c = 4\n", "broken_function(c)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m\u001b[0m(2)\u001b[0;36mbroken_function\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 1 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mbroken_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\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----> 2 \u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mxxx\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 3 \u001b[0;31m\u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 4 \u001b[0;31m\u001b[0mbroken_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n", "ipdb> quit\n" ] } ], "source": [ "%debug" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "## Python Exercises" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "1. Sum the first 50 numbers with a for loop\n", "2. Do the same thing using `numpy` arrays\n", "3. Write a function that set a value for its argument (that is an integer)\n", "4. The same but for a `numpy` arrray" ] } ], "metadata": { "anaconda-cloud": {}, "celltoolbar": "Slideshow", "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.6.2" }, "nav_menu": {}, "toc": { "navigate_menu": true, "number_sections": true, "sideBar": true, "threshold": 6, "toc_cell": false, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }