{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "CV4GS - Python tutorial" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "\n", "\n", "

Table of Contents

\n", "
\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "\n", "\n", "

Table of Contents

\n", "
\n", " \n", "
\n", "
\n", " \n", "
\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Introduction" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- **fun facts** \n", " ⇒ Python was first released in 1991 by Guido van Rossum; Python 2.0 was released on 16 October 2000, and Python 3.0 on 3 December 2008 \n", " ⇒ Python's name is derived from the British comedy group [Monty Python](https://en.wikipedia.org/wiki/Monty_Python) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* **Python versions** \n", "On 1 Janurary 2020, Python [officially dropped support](https://www.python.org/doc/sunset-python-2/) for `python2`. Throughout this course we'll be using `python3`.
\n", "Check your Python version from your terminal:\n", "```console\n", "$ python --version\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python 3.9.12\n" ] } ], "source": [ "!python --version" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "> **Note**: there are a number of differences between Python2 and Python3. Here are a few:\n", "> * print function:\n", "> ```python\n", " print 'hello world' # Python2 syntax\n", " print('hello world') # Python3 syntax\n", "> ```\n", "> * integer division:\n", "> ```python\n", " 3/2 # Python 2 => returns 1\n", " 3/2 # Python 3 => returns 1.5\n", "> ```\n", "> * unicode:\n", "> Python 2 has ASCII str() type, unicode() type, but no byte type.\n", "> Python 3, has unicode UTF-8 str() type, and byte type\n", "> ```python\n", " print(Popocatépetl) # Python2 => ERROR: non-ASCII characters not handled (e.g. accents)\n", " print(Popocatépetl) # Python3 => SUCCESS: UTF-8 characters handled (e.g. accents)\n", "> ```\n", "> * xrange & range functions to create iterable objects:\n", "> ```python\n", " xrange(5) # Python2 syntax\n", " range(5) # Python3 syntax\n", "> ```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* **interpretated language** \n", " ⇒ an interpreter processes the source file at runtime \n", " ⇒ Python does not require that you compile your program before executing it (unlike C++, Pascal, Fortran, etc.)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* **high-level language** \n", " ⇒ Python relies on easy-to-read structures that are later translated into a low-level language and run on the computer’s central processing unit (CPU)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* **object-oriented language** \n", " ⇒ allows powerful code structuring \n", " ⇒ the `object-oriented programming (OOP)` allows thinking of problems in terms of `classes` and `objects`, thereby allowing the creation of reusable patterns of code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* **general-purpose** \n", " ⇒ Python comes with a limited number of built-in libraries, making it very light weigth \n", " ⇒ a huge amount of third-party `packages`, `libraries`, and frameworks are available to handle various aspects \n", " ⇒ the installation of additional packages is managed through `package managers` (pip, conda):
\n", "```console\n", "$ pip install #>> Python's package manager\n", "$ conda install #>> Anaconda's package manager\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* **most common libraries for scientific purposes** \n", " * plotting: [`matplotlib`](http://matplotlib.org/), [bokeh](http://bokeh.pydata.org/en/latest/), [seaborn](https://seaborn.pydata.org/), [plotly](https://plotly.com/), [mayavi](http://code.enthought.com/projects/mayavi/)\n", " * data manipulation: [`numpy`](http://www.numpy.org/), [pandas](https://pandas.pydata.org/)\n", " * image: [`scikit-image`](https://scikit-image.org/), [`imageio`](https://imageio.github.io/), [pillow](https://pillow.readthedocs.io/en/stable/), [opencv](https://opencv.org/)\n", " * machine learning: [`scikit-learn`](https://scikit-learn.org/stable/), [`tensorflow/keras`](https://keras.io/), [pytorch](https://pytorch.org/)\n", " \n", "For those with experience with Matlab, see [numpy for Matlab users](https://docs.scipy.org/doc/numpy-dev/user/numpy-for-matlab-users.html)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Python basics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* print text using \"print\" \n", " ```python\n", " print('Hello World')\n", " ```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* comment using a hash character (#)\n", " ```python\n", " # this text is commented\n", " ```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* python is zero base: indexing starts at 0 (whereas Matlab starts at 1) \n", "```python\n", "a = [1, 2, 3]\n", "a[0] # access first element of list with index = 0\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "* python requires proper indenting to understand which block it corresponds to (i.e., no explicit statement to close a code block). \n", "Without proper indenting the code will not compile.\n", "```python\n", "# EX: for-loop\n", "for k in range(10):\n", " print(k)\n", "# EX: if-statement\n", "if k > 0:\n", " print(k)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* python makes extensive use of `modules` and `packages`, which are `imported` at the begining of the file. \n", "Theses can be imported if installed, or if in your PYTHONPATH.\n", "```python\n", "import sys\n", "import pandas as pd\n", "from matplotlib import pyplot as plt\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Basic data types" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Basic data types in Python include `numbers`, `booleans` and `strings`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Types: `integer`, `float`, `complex`" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n" ] } ], "source": [ "a = 1 # int = signed integer (= positive or negative whole numbers with no decimal point)\n", "print(type(a))\n", "\n", "b = 1.0 # float = floating point real values (= real numbers with a decimal point)\n", "print(type(b))\n", "\n", "c = 2.0 + 3j # complex = complex numbers (= a + bj, where a represents the real part, anb b the imaginary part)\n", "print(type(c))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### booleans" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Python, boolean variables are defined by the `True` and `False` keywords. " ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "t = True\n", "f = False\n", "\n", "print(type(t))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### strings" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### creation" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n", "\n" ] } ], "source": [ "hello = 'hello' # string with single quotes\n", "world = \"world\" # string with double quotes (same as single quote)\n", "helloworld = '''hello world ''' # string with triple quotes\n", "hellocruelworld = \"\"\" # string with triple quotes (can span multiple lines, include single/double quotes)\n", "hello 'cruel' world\n", "\"\"\" \n", "\n", "print(type(hello))\n", "print(type(world))\n", "print(type(helloworld))\n", "print(type(hellocruelworld))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### formating \n", "- using string method `.format()`" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Hello world! We are in 2024.'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'Hello {}! We are in {}.'.format('world', 2024)" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'hello cruel world'" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'{word1} {word2} {word3}'.format(word1='hello', word2='cruel', word3='world')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'3.00'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'{:.2f}'.format(3.141592) # keep only 2 decimal points\n", "'{:.2f}'.format(3) # add 2 decimal points" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- using `f-strings` (in Python 3.6+)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Hello world! We are in 2024'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "word1 = 'world'\n", "word2 = 2024\n", "f'Hello {word1}! We are in {word2}'" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- using placeholder `%` (older formatting syntax)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world! We are in 2024.\n" ] } ], "source": [ "name = 'world'\n", "year = 2024\n", "\n", "formatted_string = 'Hello %s! We are in %d.' % (name, year)\n", "print(formatted_string)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### concatenation" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'HelloWorld'" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 'Hello'\n", "y = 'World'\n", "x + y" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### class built-in methods\n", "List of all string methods in the [documentation](https://docs.python.org/3.7/library/stdtypes.html#string-methods)." ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n", "HELLO\n", " hello\n", " hello \n", "heLLo\n", "world\n", "['hello', 'world']\n" ] } ], "source": [ "s = \"hello\"\n", "print(s.capitalize()) # Capitalize a string\n", "print(s.upper()) # Convert a string to uppercase; prints \"HELLO\"\n", "print(s.rjust(7)) # Right-justify a string, padding with spaces\n", "print(s.center(7)) # Center a string, padding with spaces\n", "print(s.replace('l', 'L')) # Replace all instances of one substring with another\n", "print(' world '.strip()) # Strip leading and trailing whitespace\n", "print('hello world'.split(' ')) # Split string at specified character" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### bytes, unicode" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - unicode string\n", "type('test')\n", "type(u'test') # Note: u'strings' are unicode for backwards compatibility with python 2)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "bytes" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - byte string\n", "type(b'test') # Note: bytes can only contain ASCII literal characters (no accents)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "b'Popocat\\xc3\\xa9petl'" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - convert unicode to bytes\n", "# Note: UTF-8 is an encoding supporting accents, ASCII does not\n", "print(type('Popocatépetl'))\n", "'Popocatépetl'.encode('utf-8') # unicode is .encoded(encoding) to bytes; " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - convert byte to unicode\n", "mystring = b'test'.decode('utf-8')\n", "type(mystring)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Operators" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### arithmetic operators" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "0\n", "2\n", "1\n", "1\n", "0\n" ] } ], "source": [ "x = 1\n", "print(x + 1) # Addition\n", "print(x - 1) # Subtraction\n", "print(x * 2) # Multiplication\n", "print(x ** 2) # Exponentiation\n", "print(x % 2) # Modulus\n", "print(x // 2) # Floor division (note: since python3 dividing an int always casts to float)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### assignment operators (shortcut)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "x = 1 \n", "x += 2 # x = x + 2\n", "x -= 2 # x = x - 2\n", "x /= 2 # x = x / 2\n", "x *= 2 # x = x * 2" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "# Example:\n", "x = 1\n", "x *= 2\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Multiple variable assignments:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "a\n" ] } ], "source": [ "x, y = 1, 'a'\n", "\n", "print(x)\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### comparison operators" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 1\n", "y = 2\n", "\n", "x == y # Equal\n", "x != y # Not equal\n", "x > y # Greater than\n", "x < y # Less than\n", "x >= y # Greater than or equal to\n", "x <= y # Less than or equal to" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### logical operators\n", "Logical operators are used to combine conditional statements.\n", "\n", "Python implements all of the usual operators for Boolean logic, but uses English words rather than symbols (&&, ||, etc.):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 1\n", "\n", "x < 5 and x < 10 # Returns True if both statements are true\n", "x < 5 or x < 4 # Returns True if one of the statements is true\n", "not(x < 5 and x < 10) # Reverse the result, returns False if the result is true" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### membership operators\n", "Membership operators are used to test if a sequence is presented in an object:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "l = ['a', 'b']\n", "\n", "'a' in l # Returns True if a sequence with the specified value is present in the object\n", "'c' not in l # Returns True if a sequence with the specified value is not present in the object" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Containers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python includes several built-in container types: `lists`, `dictionaries`, `sets`, and `tuples`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `list` is a `mutable` list of elements, which can be of multiple types." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### creation" ] }, { "cell_type": "code", "execution_count": 159, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4]\n" ] } ], "source": [ "l = [] # create empty list\n", "l = list() # create empty list\n", "\n", "l = [1, 2, 3, 4, 5] # create list by comma seperated values inside square brackets\n", "l = [1, 'a', 'b', 4, 5] # lists can hold several data types\n", "l = list(range(5)) # create list of integers using the built-in function 'range'\n", "\n", "print(l)" ] }, { "cell_type": "code", "execution_count": 125, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1, 2, 3], [4, 5, 6]]\n", "[1, 2, 3, 4, 5, 6]\n", "[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]\n" ] } ], "source": [ "l1 = [1, 2, 3]\n", "l2 = [4, 5, 6]\n", "l = [l1, l2] # concatenate lists (create list of lists)\n", "print(l)\n", "\n", "l = l1 + l2 # append lists\n", "print(l)\n", "\n", "l *= 2\n", "print(l) # replicate list" ] }, { "cell_type": "code", "execution_count": 126, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "12" ] }, "execution_count": 126, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(l) # get number of elements in list" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Note: a list can only have 1 dimension\n", "```python\n", "l = [1,2,3; 4,5,6] # INVALID SYNTAX (Matlab style)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### indexing and slicing\n", "Access list elements using square brackets. \n", "Reminder: Python is zero-based, meaning the first element is accessed with the index 0
\n", "Important: the result of the slicing includes the start index, but excludes the end index" ] }, { "cell_type": "code", "execution_count": 164, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, -1, -2, 3, 4, 5]\n" ] } ], "source": [ "l = [1, 2, 3, 4, 5]\n", "\n", "# - access single element\n", "l[0] # access first element\n", "l[-1] # access last element\n", "l[-2] # access second to last element\n", "\n", "# - slice (access multiple elements)\n", "# Important: the result includes the start index, but excludes the end index\n", "l[1:3] # access 2nd & 3rd elements\n", "l[1:-2] # access 2nd until 2nd to last element\n", "l[:3] # access all elements from start until 4th element\n", "l[3:] # access all elements from 4th element until end\n", "l[::2] # access every nth element\n", "\n", "# - assign element\n", "l[0] = 0 # replace element\n", "l[1:2] = [-1, -2] # assign a sublist to a slice\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### class built-in methods" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]\n", "[1, 2, -3]\n", "[1, 0.5, 2, -3]\n", "[1, 2, -3]\n", "[-3, 1, 2]\n" ] } ], "source": [ "l = []\n", "\n", "l.append(1) # add element at the end of the list\n", "print(l)\n", "\n", "l.extend([2, -3]) # append list at the end of the list\n", "print(l)\n", "\n", "l.insert(1, .5) # insert element at index n: insert(n, value)\n", "print(l)\n", "\n", "l.pop(1) # remove element at index n: pop(n)\n", "print(l)\n", "\n", "l.sort() # sorts elements\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### iterating over lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A list is an `iterable` container, to iterate through its elements use a for-loop:" ] }, { "cell_type": "code", "execution_count": 142, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] } ], "source": [ "l = [1, 2, 3]\n", "for element in l:\n", " print(element)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To get both index and value during iteration, use the built-in function `enumerate`:" ] }, { "cell_type": "code", "execution_count": 144, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "index=0, value=1\n", "index=1, value=2\n", "index=2, value=3\n" ] } ], "source": [ "for index, element in enumerate(l):\n", " print('index={}, value={}'.format(index, element))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Use `list comprehension` to iterate through list and edit its values in a single line:" ] }, { "cell_type": "code", "execution_count": 152, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 4, 6]\n", "[4]\n", "[1, 4, 3]\n" ] } ], "source": [ "l = [1, 2, 3]\n", "\n", "ll = [elt*2 for elt in l] # list comprehension\n", "print(ll)\n", "\n", "ll = [elt*2 for elt in l if elt == 2] # list comprehension with if condition\n", "print(ll)\n", "\n", "ll = [elt*2 if elt == 2 else elt*1 for elt in l] # list comprehension with if-else condition\n", "print(ll)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### dictionaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `dictionary` stores key-value pairs, values can be retrieved via their key." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### creation" ] }, { "cell_type": "code", "execution_count": 302, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 1, 'b': 2, 'c': {'c1': 0.1, 'c2': 0.2}}\n" ] } ], "source": [ "d = {} # create empty dictionary\n", "d = dict() # create empty dictionary\n", "\n", "d = {'a':1, 'b':2, 'c':3} # create dictionary by 'key':value\n", "d = dict(a=1, b=2, c=3) # create dictionary by key=value\n", "d = dict(a=1, b=2, c=dict(c1=.1, c2=.2)) # create nested dictionaries\n", "\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 229, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{(0, 1): 0, (0, 2): 1}\n" ] } ], "source": [ "d = {1:1, 2:2, 3:3} # keys can be numeric values\n", "d = {'hello world':1, 'united we stand':1} # keys can be complex strings\n", "d = {(0,1):0, (0,2):1} # keys can be tuples\n", "\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 198, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 1, 'b': 2, 'c': 3, 'd': 4}\n" ] } ], "source": [ "d = {'a':1, 'b':2, 'c':3}\n", "d['d'] = 4 # append key to dictionary\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### accessing" ] }, { "cell_type": "code", "execution_count": 319, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "0.1\n", "1\n", "3\n" ] } ], "source": [ "d = dict(a=1, b=2, c=dict(c1=.1, c2=.2))\n", "print(d['a']) # access value using key\n", "print(d['c']['c1']) # access value in nested dictionaries\n", "print(d.get('a')) # access value using build-in method\n", "\n", "d = {1:1, 2:2, 3:3} \n", "print(d[3]) # access value using key" ] }, { "cell_type": "code", "execution_count": 200, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 1, 'b': 2, 'c': 'c'}\n" ] } ], "source": [ "d = dict(a=1, b=2, c=3)\n", "d['c'] = 'c' # replace value\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### iterating over dict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dictionaries are iterator objects, you can iterate through it using a for-loop:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "key=a, value=1\n", "key=b, value=2\n", "key=c, value=3\n" ] } ], "source": [ "d = dict(a=1, b=2, c=3)\n", "\n", "for key in d:\n", " print('key={}, value={}'.format(key, d[key]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Use `dictionary comprehension` to create or edit dictionaries:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 0, 'b': 0, 'c': 0}\n" ] } ], "source": [ "d = {key: 0 for key in ['a', 'b', 'c']} # create a dictionary with keys defined by list values\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 1, 'b': 1, 'c': 1}\n" ] } ], "source": [ "d = {key: d[key]+1 for key in d} # edit existing dictionary\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### class built-in methods" ] }, { "cell_type": "code", "execution_count": 314, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': 1, 'b': 2, 'c': 4, 'd': 5}\n" ] } ], "source": [ "# - update a dictionary with values from another dictionary\n", "d1 = dict(a=1, b=2, c=3)\n", "d2 = dict(c=4, d=5)\n", "\n", "d1.update(d2)\n", "print(d1)" ] }, { "cell_type": "code", "execution_count": 321, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] }, { "data": { "text/plain": [ "[1, 2, 3]" ] }, "execution_count": 321, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - access keys / values (returns an iterator)\n", "d = dict(a=1, b=2, c=3)\n", "\n", "d.keys()\n", "d.values()\n", "\n", "# => loop through values\n", "for v in d.values():\n", " print(v)\n", " \n", "# => return list of values\n", "list(d.values())" ] }, { "cell_type": "code", "execution_count": 327, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'b': 2, 'c': 3}\n", "1\n" ] } ], "source": [ "# - remove value\n", "d = dict(a=1, b=2, c=3)\n", "\n", "removed_value = d.pop('a')\n", "print(d)\n", "print(removed_value)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### tuples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A tuple is an `immutable` list of values, meaning they cannot be changed once created. \n", "(This also means they are hashable, and can be used as a dictionary key)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### creation" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "t = (1, 2, 3) # create tuple\n", "t = 1, 2, 3 # create tuple (parenthesis are optional)\n", "print(t)\n", "print(type(t))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### indexing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indexing and slicing work like lists." ] }, { "cell_type": "code", "execution_count": 245, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 2, 3)\n", "\n", "1\n" ] } ], "source": [ "print(t[0]) # access tuple element" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Use `tuple unpacking` to assign tuple elements to multiple variables at once:" ] }, { "cell_type": "code", "execution_count": 251, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 3]\n", "4\n" ] } ], "source": [ "a, b, c = 1, 2, 3 # unpack (parenthesis are optional)\n", "_, _, c = 1, 2, 3 # unpack and ignore elements\n", "a, *b, c = 1, 2, 3, 4 # unpack with multiple elements casted to a list (Python3 only)\n", "\n", "print(b)\n", "print(c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Combine iteration and tuple unpacking:" ] }, { "cell_type": "code", "execution_count": 311, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alice, she is 29\n", "Bob, he is 23\n", "Eve, she is 44\n" ] } ], "source": [ "students = [\n", " ('Alice', ('F', 29)),\n", " ('Bob', ('M', 23)),\n", " ('Eve', ('F', 44)),\n", "]\n", "\n", "for name, (sex, age) in students:\n", " print('{name}, {pronoun} is {age}'.format(name=name, age=age, pronoun=dict(F='she', M='he')[sex]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Notes**: \n", "* Warning: the following is also a tuple (note the trailing comma)\n", " ```python\n", " t = 1,\n", " print(t)\n", " ```\n", "* Warning: cannot change values of a tuple (immutable)\n", " ```python\n", " t[0] = 1 # will generate an error\n", " ```\n", "* Tuples are often used to return multiple values from a function\n", " ```python\n", " def multiple_values():\n", " return 1, 2, 3, 4\n", " ```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `set` is an unordered collection of distinct (unique) elements. " ] }, { "cell_type": "code", "execution_count": 295, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{0.1, 'tiger', (1, 2, 3), 'monkey'}\n", "\n", "{0.1, 'tiger', (1, 2, 3), 'monkey'}\n", "{0.1, 'tiger', (1, 2, 3), 'monkey'}\n", "{0.1, 'tiger', (1, 2, 3), 'monkey', 'zebra'}\n", "{'tiger', (1, 2, 3), 'monkey', 'zebra'}\n", "False\n" ] } ], "source": [ "s = {'tiger', 'monkey', (1,2,3), .1} # create set\n", "s = set(['tiger', 'monkey', (1,2,3), .1]) # create set\n", "print(s)\n", "print(type(s))\n", "\n", "s = {'tiger', 'monkey', 'monkey', (1,2,3), .1} # elements are unique (duplicates are ignored)\n", "print(s)\n", "\n", "s.add('monkey') # adding an existing element does nothing\n", "print(s)\n", "\n", "s.add('zebra') # add element\n", "print(s)\n", "\n", "s.remove(.1) # remove element\n", "print(s)\n", "\n", "print('cat' in s) # check if an element is in a set" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Note: standard \"trick\" to remove duplicates from a list (WARNING: will change the list order!)" ] }, { "cell_type": "code", "execution_count": 298, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 5, 6]" ] }, "execution_count": 298, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = [3, 5, 1, 6, 2, 1, 3, 5]\n", "list(set(data)) # remove duplicates by converting list to set" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Control flow statements" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### if statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python uses the `if`, `elif`, and `else` clauses to conditionally execute blocks of statements." ] }, { "cell_type": "code", "execution_count": 337, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x is negative\n" ] } ], "source": [ "x = -10\n", "\n", "if x < 0:\n", " print(\"x is negative\")\n", "elif x > 0:\n", " print(\"x is positive\")\n", "else:\n", " print(\"x = 0\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Any non-zero number or non-empty string, tuple, list, or dictionary evaluates as true:" ] }, { "cell_type": "code", "execution_count": 343, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "List is empty\n", "This is evaluated as False\n" ] } ], "source": [ "# - evaluate a string\n", "x = []\n", "if x:\n", " print('List is not empty')\n", "else:\n", " print('List is empty')\n", "\n", "# - evaluate a number\n", "y = 0\n", "if y:\n", " print('This is evaluated as True')\n", "else:\n", " print('This is evaluated as False')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### for loop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python uses the `for` statement to loop through an `iterable` object." ] }, { "cell_type": "code", "execution_count": 348, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c\n", "i\n", "a\n", "o\n" ] } ], "source": [ "for letter in 'ciao':\n", " print(letter)" ] }, { "cell_type": "code", "execution_count": 350, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "h\n", "o\n", "l\n", "a\n" ] } ], "source": [ "for elt in ['h', 'o', 'l', 'a']:\n", " print(elt)" ] }, { "cell_type": "code", "execution_count": 355, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for idx in range(5):\n", " print(idx)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Use the built-in function `enumerate` to get both index and value during iteration:" ] }, { "cell_type": "code", "execution_count": 352, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "index=0, value=h\n", "index=1, value=o\n", "index=2, value=l\n", "index=3, value=a\n" ] } ], "source": [ "l = ['h', 'o', 'l', 'a']\n", "for index, element in enumerate(l):\n", " print('index={}, value={}'.format(index, element))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### while loop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python uses the `while` clause to loop over body as long as the condition is True." ] }, { "cell_type": "code", "execution_count": 354, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n", "3\n", "2\n", "1\n", "0\n" ] } ], "source": [ "a = 5\n", "while a>0:\n", " a -= 1\n", " print(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### try-except statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python supports exception handling with the try statement, which includes `try`, `except`, `finally`, and `else` clauses." ] }, { "cell_type": "code", "execution_count": 385, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Try dividing by 0\n", "You fool!\n" ] } ], "source": [ "try:\n", " print('Try dividing by 0')\n", " 1 / 0\n", "except:\n", " print('You fool!')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### exceptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Exceptions` happen at runtime and are used for error handling. Here are some standard errors:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* _ZeroDivisionError_" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m1\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "1 / 0" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* _KeyError_" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "ename": "KeyError", "evalue": "'b'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "Input \u001b[0;32mIn [26]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m d \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mdict\u001b[39m(a\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m)\n\u001b[0;32m----> 2\u001b[0m \u001b[43md\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mb\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\n", "\u001b[0;31mKeyError\u001b[0m: 'b'" ] } ], "source": [ "d = dict(a=1)\n", "d['b']" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### handling exceptions " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the cells below, we generate an error called \"ZeroDivisionError\" (triggered when a number is divided by zero), and we catch that error with the `except` statement to run another code block." ] }, { "cell_type": "code", "execution_count": 371, "metadata": {}, "outputs": [], "source": [ "# Set function to computer the inverse value of the parsed variable.\n", "def inverse(a):\n", " return 1. / a" ] }, { "cell_type": "code", "execution_count": 372, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "float 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[1;32m 1\u001b[0m \u001b[0;31m# Calling the inverse function on a 0 returns the error 'ZeroDivisionError'\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[0minverse\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[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36minverse\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Set function to computer the inverse value of the parsed variable.\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;32mdef\u001b[0m \u001b[0minverse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\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[0;32mreturn\u001b[0m \u001b[0;36m1.\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m: float division by zero" ] } ], "source": [ "# Calling the inverse function on a 0 returns the error 'ZeroDivisionError'\n", "inverse(0)" ] }, { "cell_type": "code", "execution_count": 402, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Caught \"ZeroDivisionError\" in the expression.\n", "b = 99999\n" ] } ], "source": [ "# Test for the 'ZeroDivisionError'\n", "\n", "try:\n", " b = inverse(0)\n", "except ZeroDivisionError:\n", " # execute if 'ZeroDivisionError' caught\n", " print('Caught \"ZeroDivisionError\" in the expression.')\n", " b = 99999\n", "\n", "print('b =', b)" ] }, { "cell_type": "code", "execution_count": 400, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No exception occurred\n", "Try statement finished\n", "b = 1.0\n" ] } ], "source": [ "# Test for various error types\n", "\n", "try:\n", " b = inverse(1)\n", "except (ZeroDivisionError, KeyError):\n", " # execute if 'ZeroDivisionError' or 'KeyError' caught\n", " b = 99999\n", "except ValueError:\n", " # execute if 'ValueError' caught\n", " b = 88888\n", "else:\n", " # excetute if no exceptions caught\n", " print('No exception occurred')\n", "finally:\n", " # always execute this\n", " print('Try statement finished')\n", "\n", "print('b =', b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### raise custom exceptions" ] }, { "cell_type": "code", "execution_count": 391, "metadata": {}, "outputs": [ { "ename": "Exception", "evalue": "x should not exceed 5. The value of x was: 10", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\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 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m10\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[0mx\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m5\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[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'x should not exceed 5. The value of x was: {}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\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;31mException\u001b[0m: x should not exceed 5. The value of x was: 10" ] } ], "source": [ "x = 10\n", "if x > 5:\n", " raise Exception('x should not exceed 5. The value of x was: {}'.format(x))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### pass statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The body of a Python compound statement cannot be empty—it must contain at least one statement. The `pass` statement, which performs no action, can be used as a placeholder when a statement is syntactically required but you have nothing specific to do. " ] }, { "cell_type": "code", "execution_count": 361, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def function_to_prepare():\n", " pass" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### break statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `break` statement is allowed only inside a loop body (`for` or `while` loop). When break executes, the loop terminates. " ] }, { "cell_type": "code", "execution_count": 360, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "Index >= 2, stopping the loop\n" ] } ], "source": [ "for idx in range(5):\n", " print(idx)\n", " \n", " if idx>=2:\n", " print('Index >= 2, stopping the loop')\n", " break" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### assert statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use `assert` statement to test that a certain condition is met. If this condition is True, the program can continue, otherwise you can have the program throw an AssertionError exception." ] }, { "cell_type": "code", "execution_count": 394, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "AssertionError", "evalue": "This value of x should be positive", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAssertionError\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 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mx\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\"This value of x should be positive\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mAssertionError\u001b[0m: This value of x should be positive" ] } ], "source": [ "x = -1\n", "assert (x > 0), \"This value of x should be positive\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Functions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Python functions are defined using the `def` keyword. \n", "> * the body of the function is indented (always use 4 spaces for one indentation level)\n", "> * the returned value preceded by the `return` keyword; (functions can have multiple return statements)\n", "> * arguments can be parsed as positional arguments (`args`), i.e. a list of comma seperated values: func(a, b, c)\n", "> * arguments can be parsed as keyword arguments (`kwargs`), which have a default value if not explicitely parsed: func(spam=1, eggs=2)\n", "> * when using args and kwargs, args must always come before kwargs: func(a, spam=1, eggs=2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### parse positional arguments" ] }, { "cell_type": "code", "execution_count": 419, "metadata": {}, "outputs": [], "source": [ "def add(x, y):\n", " return x + y\n", "\n", "def inverse(x):\n", " if x != 0:\n", " return 1/x\n", " else:\n", " print('warning: cannot return the inverse of 0, returning None')\n", " return None" ] }, { "cell_type": "code", "execution_count": 420, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 420, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add(2, 2)" ] }, { "cell_type": "code", "execution_count": 421, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "0.5" ] }, "execution_count": 421, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inverse(2)" ] }, { "cell_type": "code", "execution_count": 422, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "warning: cannot return the inverse of 0, returning None\n" ] } ], "source": [ "inverse(0)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### parse keyword arguments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arguments can be parsed as keyword arguments, and default values can be set." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def greetings(language='english', name='Jake'):\n", " if language == 'english':\n", " print('Hello {}!'.format(name))\n", " elif language == 'spanish':\n", " print('Hola {}!'.format(name))\n", " else:\n", " print('I dont speak this language.')" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hola Emiliano!\n", "Hola Jake!\n" ] } ], "source": [ "greetings(language='spanish', name='Emiliano')\n", "greetings(language='spanish') # name not parsed => will take use default value defined in funtion" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Jake!\n" ] } ], "source": [ "d = dict(language='english')\n", "greetings(**d) # unpack dictionary keys-values as keywarg arguments" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### set documentation" ] }, { "cell_type": "code", "execution_count": 459, "metadata": {}, "outputs": [], "source": [ "def addone(a):\n", " '''This function is used to add one to the parsed variable.'''\n", " return a + 1" ] }, { "cell_type": "code", "execution_count": 460, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "'This function is used to add one to the parsed variable.'" ] }, "execution_count": 460, "metadata": {}, "output_type": "execute_result" } ], "source": [ "addone.__doc__" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### warning: calls by value or reference" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Call by `value`**: for primitive variables (ex: numbers), Python copies the content of the variable into the function. " ] }, { "cell_type": "code", "execution_count": 442, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n" ] } ], "source": [ "def addone(a):\n", " a = a + 1\n", "\n", "n = 3\n", "addone(n) # => variable 'n' is copied to new variable 'a' inside the function => 'a' is changed 'n' is not\n", "print(n) " ] }, { "cell_type": "code", "execution_count": 443, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n" ] } ], "source": [ "# => to change 'n' we need to return the copied variable 'a' which was changed\n", "def addone(a):\n", " a = a + 1\n", " return a\n", "\n", "n = 3\n", "n = addone(n)\n", "print(n)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Call by `reference`**: for complex variables (ex: lists), Python does not copy the variable inside the function, instead it references it. This mean that the parsed variable will suffer the changes, even though the variable is not returned from the function." ] }, { "cell_type": "code", "execution_count": 445, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, -10, 3, 4]\n" ] } ], "source": [ "mylist = [1, 2, 3, 4]\n", "\n", "def func(a):\n", " a[1] = -10\n", "\n", "func(mylist)\n", "print(mylist) # => the array is modified even though the list was not returned from the function!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Intermediate Exercises" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "
\n", " 1. Write a function that takes two values and returns the largest one (max), and document it\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", "\n", "def get_max(a, b):\n", " \"\"\"\n", " Return the larger of two values.\n", "\n", " Example:\n", " >>> get_max(3.5, 1.2)\n", " 3.5\n", " \"\"\"\n", "\n", " # Using numpy:\n", " # import numpy as np\n", " # return np.maximum(a, b)\n", "\n", " # Using built-in method:\n", " return max(a, b)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "
\n", " 2. Write a function that computes the ratio between two values, and prints a warning message when the denominator is 0\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", "\n", "def get_ratio(a, b):\n", " \"\"\"\n", " Compute the inverse of two values.\n", "\n", " Example:\n", " >>> get_ratio(5, 2)\n", " 2.5\n", " >>> get_ratio(3, 0)\n", " Warning: Division by zero. The result is undefined.\n", " \"\"\"\n", " if b == 0:\n", " print(\"Warning: Division by zero. The result is undefined.\")\n", " raise ZeroDivisionError(\"Denominator cannot be zero.\")\n", " return a / b\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "
\n", " 3. Build a for loop which iterates through numbers ranging from 0 to 20, and as it iterates it creates a list containing the squared value of the iterated value. Exist the loop when the iterator exceeds 10.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", "\n", "# Solution without list comprehension:\n", "squared_values = [] # Initialize an empty list to store squared values\n", "for num in range(21): # Iterate through numbers from 0 to 20\n", " if num > 10:\n", " break # Exit the loop if the iterator exceeds 10\n", " squared_values.append(num ** 2) # Square the number and append to the list\n", "print(squared_values)\n", "\n", "# Solution with list comprehension\n", "squared_values = [num ** 2 for num in range(21) if num <= 10]\n", "print(squared_values)\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "
\n", " 4. Create a dictionnary a with various volcanoes as keys, and their altitude as values. Print the altitude of your favourite volcanoe from the dictionary.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", "\n", "# Create the dictionary with volcanoes and their altitudes\n", "volcano_altitudes = {\n", " \"Popocatépetl\": 5426,\n", " \"Etna\": 3329,\n", " \"Mount Fuji\": 3776\n", "}\n", "\n", "# Print the altitude of your favorite volcano\n", "volcano_name = \"Popocatépetl\"\n", "print(f\"The altitude of {volcano_name} is {volcano_altitudes[volcano_name]} meters.\")\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Classes, Methods, Attributes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Python, everything is an `object`, even functions and attributes. \n", "`OOP` = Object Oriented Programing" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* `Classes` are defined with the `class` keyword. \n", " ‐ class names are usually Capitalized and use CamelCase \n", " ‐ classes are instantiated with () \n", " ‐ class attributes are fined in __init__ (not compulsory, but considered good practice) \n", "* `Methods` are functions inside classes, and are defined with the `def` keyword \n", " ‐ function names are usually lower case \n", "* `Attributes` are set like that instance.attribute = value, and are also accessed via instance.attribute" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "class Volcano():\n", " \n", " def __init__(self, name):\n", " self.name = name\n", " self.type = 'mountain' # public attribute\n", " self.__imminentexplosion = False # private attribute (starts with double underscore)\n", " \n", " def print_name(self):\n", " print('The volcano name is', self.name)\n", " \n", " def set_altitude(self, altitude):\n", " self.altitude = altitude" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# - instantiate class\n", "volc = Volcano('colima')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "'mountain'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - get class attribute (public):\n", "volc.type " ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# - private class attribute unaccesible\n", "# volc.__imminentexplosion # command returns 'AttributeError'" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The volcano name is colima\n" ] } ], "source": [ "# - call class method:\n", "volc.print_name() " ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3820\n" ] } ], "source": [ "# - set attribute through class method:\n", "volc.set_altitude(3820)\n", "print(volc.altitude)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "{'name': 'colima',\n", " 'type': 'mountain',\n", " '_Volcano__imminentexplosion': False,\n", " 'altitude': 3820}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - get class attributes (public + private) as dictionary\n", "volc.__dict__" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - check class instance\n", "print(type(volc))\n", "isinstance(volc, Volcano)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### inheritence" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A class can `inherit` methods and attributes from a parent class.\n", "> `super().method()` let's you call an instances parent's method from an instance method" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class ExplosiveVolcano(Volcano):\n", " def __init__(self, name):\n", " super().__init__(name)\n", " \n", " def set_expected_VEI(self, VEI):\n", " '''Volcanic Explosivity Index (VEI) is a relative measure of the explosiveness of volcanic eruptions.'''\n", " self.expected_VEI = VEI" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# - instantiate class which inherited from class Volcano\n", "popo = ExplosiveVolcano('Popocatépetl') # needs to parse arguments for parent class Volcano" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "popo.set_expected_VEI(5)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "print(popo.expected_VEI)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A class can inherit from multiple classes:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "class Mountain():\n", " def __init__(self):\n", " self.category = 'geology'" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "class SuperVolcano(ExplosiveVolcano, Mountain):\n", " # Note: because ExplosiveVolcano already inherits from Volcano, should not inherit both\n", " \n", " def __init__(self, name):\n", " super().__init__(name)\n", " self.info = 'stay away'\n", " \n", " def breathe(self):\n", " print(\"breathing\")" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "yellowstone = SuperVolcano('Yellow Stone')" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "stay away\n" ] } ], "source": [ "print(yellowstone.info)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### add build-in instances" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Example: `__str__` and `__repr__` instances" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">* instance description ugly by default: <__main__.ExplosiveVolcano at 0x7fb66dca6160>\n", ">* \\_\\_str\\_\\_() is supposed to give a nice string representation of the class, but uses \\_\\_repr\\_\\_() as a fallback" ] }, { "cell_type": "code", "execution_count": 514, "metadata": {}, "outputs": [], "source": [ "class ExplosiveVolcano(Volcano):\n", " def __init__(self, name):\n", " super().__init__(name)\n", " \n", " def set_expected_VEI(self, VEI):\n", " '''Volcanic Explosivity Index (VEI) is a relative measure of the explosiveness of volcanic eruptions.'''\n", " self.expected_VEI = VEI\n", " \n", " def __repr__(self):\n", " return '< Volcano: name=' + self.name + '>'" ] }, { "cell_type": "code", "execution_count": 516, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "popo = ExplosiveVolcano('Popocatépetl') # needs to parse arguments for parent class Volcano" ] }, { "cell_type": "code", "execution_count": 519, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "< Volcano: name=Popocatépetl>\n" ] } ], "source": [ "print(popo)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Modules and packages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* a `module` is python file, which can be imported if in your `PYTHONPATH`\n", "* a `package` is a collection of python modules, in practice as a directory containing python modules and a `__init__.py` file. \n", "Packages can be imported as a whole, or only modules of it can be imported." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### import" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import the `numpy` package:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "import numpy" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "numpy.add(2,3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Import the `numpy` package using a shorter name (recommended):" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add(2,3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Import a specific function from numpy:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "from numpy import add" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add(2,3)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from numpy import add as npadd" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "npadd(2,3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Import everything from the package in your current workspace using `*` (not recommended):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from numpy import * # not recommended" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Check version of a module:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'1.21.5'" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.__version__" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Check where the module is located:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'/home/balam/anaconda3/lib/python3.9/site-packages/numpy/__init__.py'" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.__file__" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Check out module content (using Linux built-in `cat` command):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!cat /home/balam/anaconda3/lib/python3.9/site-packages/numpy/__init__.py" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Check out package architecture (using Linux third-party `tree` command):" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```bash\n", "$ sudo apt install tree\n", "```" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "!tree /home/balam/anaconda3/lib/python3.9/site-packages/numpy/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### install third-party packages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Third-party packages are usually installed using `package managers`:\n", "- `pip` => Python Packaging Authority’s recommended tool for installing packages from the Python Package Index ([PyPI](https://pypi.org/))\n", "```console\n", "$ pip install \n", "```\n", "- `conda` => Anaconda's package manager for installing packages from the [Anaconda repository](https://repo.anaconda.com/) and [Anaconda cloud](https://anaconda.org/):\n", "```console\n", "$ conda install \n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
Note: there are some differences between the `pip` and `conda`, see [here](https://www.anaconda.com/blog/understanding-conda-and-pip) for details.
\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### create packages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can create your own packages and modules to reuse your code in an organized manner." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### create directory and python module" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "1. **Create directory for python package:**" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "!mkdir /home/khola/Documents/CODE/python/volcano/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "2. **Create empty `__init__.py` file to tell python the directory is a package:**" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "!touch /home/khola/Documents/CODE/python/volcano/__init__.py" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "3. **Create python script:**" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting /home/khola/Documents/CODE/python/volcano/mymodule.py\n" ] } ], "source": [ "%%writefile /home/khola/Documents/CODE/python/volcano/mymodule.py \n", "\n", "import numpy\n", "\n", "myvariable1 = 1\n", "myvariable2 = 2\n", "\n", "def add(x,y):\n", " return x+y" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "4. **Check result:**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Install Linux third-party `tree` command:\n", "```bash\n", "$ sudo apt install tree\n", "```" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": true }, "outputs": [], "source": [ "!tree /home/khola/Documents/CODE/python/" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### add path to .bashrc (on Linux)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You should add the following line to your `.bashrc` file (in Linux):\n", "```console\n", "export PYTHONPATH=/path/to/your/python/dir\n", "#export PYTHONPATH=/home/khola/Documents/CODE/python\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The cell below adds the line 'export PYTHONPATH=/home/khola/Documents/CODE/python' to the end of your .bashrc file. " ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [], "source": [ "#!echo 'export PYTHONPATH=/home/khola/Documents/CODE/python' >> ~/.bashrc" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Check results:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "else\r\n", " if [ -f \"/home/khola/anaconda3/etc/profile.d/conda.sh\" ]; then\r\n", " . \"/home/khola/anaconda3/etc/profile.d/conda.sh\"\r\n", " else\r\n", " export PATH=\"/home/khola/anaconda3/bin:$PATH\"\r\n", " fi\r\n", "fi\r\n", "unset __conda_setup\r\n", "# <<< conda initialize <<<\r\n", "\r\n" ] } ], "source": [ "!tail /home/khola/.bashrc # replace with your path" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Source your file (or restart your computer):" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "# !source ~/.bashrc" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### import your module" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "from volcano import mymodule" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "print(mymodule.myvariable1)" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mymodule.add(2,3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### make packages installable" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "TODO" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Functional Programming" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Python supports functional programming with `list/dict/set comprehensions`, `map`, `reduce`, etc." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "> Functional programming is a programming paradigm — a style of building the structure and elements of computer programs — that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data ([wikipedia](https://en.wikipedia.org/wiki/Functional_programming))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### list/dict comprehension" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 2, 4, 6, 8]\n", "[4]\n", "[0, 1, 4, 3, 4]\n" ] } ], "source": [ "# - list comprehension\n", "squares = [x*2 for x in range(5)] # list comprehension\n", "print(squares)\n", "\n", "squares = [x**2 for x in range(5) if x == 2] # list comprehension with if condition\n", "print(squares)\n", "\n", "squares = [x**2 if x == 2 else x*1 for x in range(5)] # list comprehension with if-else condition\n", "print(squares)" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "{0: '0', 1: '1', 2: '4', 3: '9', 4: '16'}" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - dictionary comprehension\n", "squares_d = {x: str(x ** 2) for x in range(5)}\n", "squares_d" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### map" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`map` maps a function to an iterable:" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[range(0, 0), range(0, 1), range(0, 2), range(0, 3), range(0, 4)]" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list_of_iteratables = [range(x) for x in range(5)]\n", "list_of_iteratables" ] }, { "cell_type": "code", "execution_count": 105, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3]" ] }, "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(0, 4))" ] }, { "cell_type": "code", "execution_count": 106, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 106, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = map(sum, list_of_iteratables)\n", "m" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[0, 0, 1, 3, 6]" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(m)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "### functools" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "skip" } }, "source": [ "`reduce` and `filter` have been moved to functools package" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### lambda functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`lambda` functions are `anonymous` functions, i.e. functions that are not bound to a name." ] }, { "cell_type": "code", "execution_count": 109, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def f(x): return x**2 # standard function" ] }, { "cell_type": "code", "execution_count": 110, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "g = lambda x: x**2 # lambda function" ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n", "4\n" ] } ], "source": [ "print(f(2))\n", "print(g(2))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Code style" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Python code style is defined in [PEP8](https://www.python.org/dev/peps/pep-0008/) (**P**ython **E**nhancement **P**roposal).\n", "\n", "Some key rules:\n", "* use four spaces for indenting, nothing else\n", "* spaces around operators (but not for keyword arguments or default values)\n", "* spaces behind commas, no spaces around braces or parenthesis\n", "* variable names at least three letters\n", "* classes use CamelCase\n", "* everything else snake_case\n", "* two empty lines before classes and functions\n", "* one empty lines before methods\n", "* 78 characters per line\n", "* tools exist to automatically check syntax in your editor\n", "* tools: `pep8`, `flake8`, etc" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Not covered" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* function `decorators`\n", "* `iterators`, `generators`, `yield` keyword\n", "* `context manangers` for elegant file reading\n", "* `global` variables and `scope`\n", "* and so much more!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Final Exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " 1. Write a class Rectangle constructed by a length and width and a method which will compute the area of a rectangle\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", "class Rectangle:\n", " def __init__(self, length, width):\n", " self.length = length\n", " self.width = width\n", "\n", " def compute_area(self):\n", " return self.length * self.width\n", "\n", "# Example usage:\n", "rectangle = Rectangle(5, 10)\n", "print(f\"Area of rectangle = {rectangle.compute_area()}\")\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "
\n", " 2. Write in the most condensed form, a way to edit a list of integers ranging from -10 to 10 with step 2, taking the squared value of negative values and the double of positive values.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Solution:**\n", "```python\n", " [x**2 if x<2 else x*2 for x in range(-10, 10, 2)]\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "181px", "width": "209px" }, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "308.6px" }, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 4 }