From db7e34de3455732a392b8361b1136f1780d190da Mon Sep 17 00:00:00 2001 From: Nicola Spallanzani <n.spallanzani@cineca.it> Date: Tue, 24 Oct 2017 22:45:06 +0200 Subject: [PATCH] add notebooks --- 01-Introduction_to_Python.ipynb | 5756 +++++++++++++++++++++++++++++++ 02-Introduction_to_Python.ipynb | 3413 ++++++++++++++++++ 03-Introduction_to_Python.ipynb | 2154 ++++++++++++ 3 files changed, 11323 insertions(+) create mode 100644 01-Introduction_to_Python.ipynb create mode 100644 02-Introduction_to_Python.ipynb create mode 100644 03-Introduction_to_Python.ipynb diff --git a/01-Introduction_to_Python.ipynb b/01-Introduction_to_Python.ipynb new file mode 100644 index 0000000..d739e87 --- /dev/null +++ b/01-Introduction_to_Python.ipynb @@ -0,0 +1,5756 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Outlook\n", + "\n", + "* Philosophy \n", + "* Interpreter\n", + "* Built-in types and operations \n", + "* Program file\n", + "* Built-in containers\n", + " * Tuples\n", + " * Lists\n", + " * Sets\n", + " * Dicts" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Outlook\n", + "\n", + "* Flow control contructs\n", + " * if-elif-else\n", + " * For loops\n", + " * While loops\n", + "* Object reference\n", + "* Functions\n", + " * Argument Passing\n", + " * Doc string\n", + " * Lambda functions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Outlook\n", + "\n", + "* Sequences\n", + " * Functional programming\n", + " * List comprehension\n", + "* Output representation\n", + " * str and repr\n", + " * String formatting\n", + "* Classes \n", + " * Instances \n", + " * Methods\n", + " * Attributes\n", + " * Inheritance" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Outlook\n", + "\n", + "* Iterables and Iterators\n", + "* Introspection\n", + "* Modules\n", + " * Packages\n", + " * pydoc and help()\n", + " * Program arguments\n", + "* File I/O\n", + "* Error handling" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## philosophy\n", + "\n", + "Python is a programming language with many good features:\n", + "\n", + "* Very easy to use\n", + "* Easy to learn (looks like pseudo-coding)\n", + "* Excellent readability (there is only one way to do anything)\n", + "* Excellent portability\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## philosophy\n", + "\n", + "* Do not call it a “scripting languageâ€! Although it can be used as such, it is much more.\n", + "* It is an high level language, modern, complete, with which it is possible to realize highly complex software.\n", + "* It is an interpreted language, but it would be more appropriate to call it \"dynamic language\".\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## philosophy\n", + "\n", + "* A dynamic language is a highÂlevel language in which many of the controls are executed run-time, while in other languages they are done at compile time.\n", + "\n", + "* Actually python \"compile\" the source into bytecode that runs on a virtual machine (like Java).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## philosophy\n", + "\n", + "It is a multiparadigm language:\n", + "* Imperative\n", + "* Object-oriented\n", + "* Functional\n", + "* Structural\n", + "* Aspect-oriented\n", + "* Design by contract (with an extension)\n", + "* ...\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## The Zen of python\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Zen of Python, by Tim Peters\n", + "\n", + "Beautiful is better than ugly.\n", + "Explicit is better than implicit.\n", + "Simple is better than complex.\n", + "Complex is better than complicated.\n", + "Flat is better than nested.\n", + "Sparse is better than dense.\n", + "Readability counts.\n", + "Special cases aren't special enough to break the rules.\n", + "Although practicality beats purity.\n", + "Errors should never pass silently.\n", + "Unless explicitly silenced.\n", + "In the face of ambiguity, refuse the temptation to guess.\n", + "There should be one-- and preferably only one --obvious way to do it.\n", + "Although that way may not be obvious at first unless you're Dutch.\n", + "Now is better than never.\n", + "Although never is often better than *right* now.\n", + "If the implementation is hard to explain, it's a bad idea.\n", + "If the implementation is easy to explain, it may be a good idea.\n", + "Namespaces are one honking great idea -- let's do more of those!\n" + ] + } + ], + "source": [ + "import this" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## disavtanges?\n", + "\n", + "Python is often considered a slow language. To a large extent this is true: it is slower than Java, for \n", + "example.\n", + "\n", + "But the speed is not always the bottleneck. Often, the management of the complexity is a problem more important than speed.\n", + "\n", + "However, there are several ways to make faster the \"critical\" parts of a python program.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## performance \n", + "\n", + "“People are able to code complex algorithms in much less time by using a high-level language like \n", + "Python (e.g., also C++). There can be a performance penalty in the most pure sense of the \n", + "term.â€\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## optimization\n", + "\n", + "\"The best performance improvement is the transition from the nonworking to the working state.\"\n", + "--John Ousterhout\n", + "\n", + "\"Premature optimization is the root of all evil.\"\n", + "--Donald Knuth\n", + "\n", + "\"You can always optimize it later.\"\n", + "-- Unknown\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python 2 / Python 3\n", + "\n", + "* There are two main branches of development of python:\n", + " * python2: it is a “dead†branch, that is maintained, but that will not undergo updates / evolution\n", + " * python3: it is the new python, actually still little used compared to python2.\n", + "* The differences are not huge, also there is the utility 2to3 to convert code from the old to the new python.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python 3\n", + "\n", + "* We will take care mainly of python3.\n", + "* I will try to point out the main differences.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## intepreter\n", + "\n", + "* Python is an interpreted language\n", + "* The interpreter performs a compilation from source to bytecode, which is then executed on a virtual machine, as in Java\n", + "* The interpreter is also an excellent \"calculator\", to be used in interactive!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2**1024" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## intepreter\n", + "\n", + "* When used in interactive mode, the interpreter acts a little differently.\n", + "* This is the prompt: “>>>†\n", + "* If an expression has a value, it is printed automatically:\n", + "\n", + "<pre>\n", + ">>> 34 + 55 - 2\n", + "87\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## intepreter\n", + "\n", + "* Any error can occur during the execution of the interpreter in interactive mode, the interpreter survives, even in case of SyntaxError:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "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<ipython-input-3-67a69f72677d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m5\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" + ] + } + ], + "source": [ + "5/0" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'fact' 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<ipython-input-4-dd06d576a896>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfact\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'fact' is not defined" + ] + } + ], + "source": [ + "fact(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (<ipython-input-5-0dc3d51d84fc>, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"<ipython-input-5-0dc3d51d84fc>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m @@@ausfd?=\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "@@@ausfd?=" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## print() \n", + "\n", + "To print on standard output you may use the print() function.\n", + "\n", + "It can take any number of arguments:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 2 4\n", + "6\n" + ] + } + ], + "source": [ + "print(0, 2, 4)\n", + "print(6)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 2 46\n" + ] + } + ], + "source": [ + "print(0, 2, 4, end='')\n", + "print(6)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "\n", + "Please note, in python2 print is an operator:\n", + "\n", + "<pre>\n", + ">>> print 1, 2, 3\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Built-in types and operations" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## integers\n", + "\n", + "* In python the integers have arbitrary precision; This allowed us to calculate `2**1024` without problems.\n", + "* Any integer whose definition can be contained in the RAM of your computer is permitted.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "\n", + "In python2 there are two types of integers: \n", + "* int for integers up to `2**63-1` (see sys.maxint)\n", + "* long for integers of any size!\n", + "The int values are automatically converted into long as \n", + "needed:\n", + "\n", + "<pre>\n", + ">>> print a, type(a)\n", + "9223372036854775807 <type 'int'>\n", + ">>> a += 1\n", + ">>> print a, type(a)\n", + "9223372036854775808 <type 'long'>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## floating point \n", + "The floating point numbers are represented by the type _**float**_:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5.562684646268003e-309" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2.0**-1024" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "float" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(2.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "The floating point numbers have finite precision:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "ename": "OverflowError", + "evalue": "(34, 'Numerical result out of range')", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mOverflowError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-10-7897dac30894>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m2.0\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m2048\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mOverflowError\u001b[0m: (34, 'Numerical result out of range')" + ] + } + ], + "source": [ + "2.0**+2048" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## integer division\n", + "\n", + "In python, dividing two integers produces a float:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10 / 4" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "When you want the division with truncation, you can use the operator //:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10 // 4" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "Despite being highly atypical compared to other languages, this is very convenient." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## division with truncation\n", + "\n", + "The operator // division with truncation is also \n", + "available for the float:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.5" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10.0 / 4.0" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2.0" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10.0 // 4.0" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "\n", + "In python2, integer division produces an integer, \n", + "and it matches with the division with truncation." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## divmod\n", + "\n", + "Sometimes it is helpful to have both the quotient and the remainder of a integer division; you can use the divmod() function\n", + "\n", + "This function returns two values, the quotient and the remainder (or modulo)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 2)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "divmod(10,4)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (interactive mode)\n", + "\n", + "<pre>\n", + "Do the following:\n", + ">>> 2**1024\n", + ">>> 100/3\n", + ">>> 100//3\n", + ">>> 100.0/3\n", + ">>> 100.0//3\n", + ">>> 100%3\n", + ">>> divmod(100, 3)\n", + "</pre>" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(33, 1)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "divmod(100,3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## complex\n", + "There is a `complex` type" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(6+0j)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = 3.0 + 4.0j\n", + "w = 3.0 - 4.0j\n", + "z+w" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(25+0j)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z*w" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "complex" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(z)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.0 4.0 5.0\n" + ] + } + ], + "source": [ + "print(z.real, z.imag, abs(z))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## variables\n", + "\n", + "You can assign to any object a symbolic name, which does not need to be declared." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "a = 5\n", + "b = 3.2\n", + "c = a\n", + "C = b # it's not \"c\", it's another variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## variables\n", + "\n", + "Although it is a bit premature to explain it now, actually __symbolic names a, b, c and C are not \n", + "variables.__\n", + "\n", + "Moreover, the symbol \"=\" is not at all what it seems!\n", + "\n", + "For now anyway we can continue \"pretending\" that these symbols are variables and that \"=\" execute an assignment or copy (as in C, C++ or Fortran).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## operators\n", + "\n", + "Common operators are available:\n", + "* \\+ (sum, concatenation)\n", + "* \\- (subtraction)\n", + "* \\* (product)\n", + "* / (division)\n", + "* // (integer division, this is new)\n", + "* % (modulo)\n", + "* ...\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## binary operators\n", + "\n", + "Like in C, binary operators are associated to assignment operators:\n", + "* += (increase)\n", + "* -= (decrease)\n", + "* ...\n", + "therefore," + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "14" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = 10\n", + "a += 4\n", + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## strings\n", + "\n", + "* The type str is commonly used for the strings. It can handle unicode strings.\n", + "* They can be created either with single quotes ('alpha') or double quotes (“alphaâ€)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'alphabeta'" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"alpha\" + 'beta'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "Strings can be printed in 2 ways: \n", + "* If function print() is used, the string content is shown\n", + "\n", + "```python\n", + ">>> print(\"Hello, \" + \"world!\")\n", + "Hello, world!\n", + "```\n", + "\n", + "* In the interactive intepreter, if we write an expression that produces a string, the content will be shown with quotes:\n", + "\n", + "```python\n", + ">>> \"Hello, \" + \"world!\"\n", + "'Hello, world!'\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "* Triple quotes: `“â€â€` or `'''`, can be used for strings that span over more than one line, or that contain single or double quotes (or the other triple quotes):" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This string spans over two lines,\n", + "and contains 'single quotes', \"double quotes\" and \n", + "'''triple quotes'''\n" + ] + } + ], + "source": [ + "a = \"\"\"This string spans over two lines,\n", + "and contains 'single quotes', \"double quotes\" and \n", + "'''triple quotes'''\"\"\"\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "* Escape characters are more or less like in C code:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "alpha\n", + "beta\tgamma\n" + ] + } + ], + "source": [ + "print(\"alpha\\nbeta\\tgamma\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "* It's possible to create raw strings (escape characters will not be interpreted):" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "alfa\\nbeta\\tgamma\n" + ] + } + ], + "source": [ + "print(r\"alfa\\nbeta\\tgamma\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "* This is particular helpful in defining regular expression" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "It is possible to operate on strings in different ways:\n", + "\n", + "Try yourself on a python interpreter\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "s = \"Hello, world!\"" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'hello, world!'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.lower()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'HELLO, WORLD!'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.upper()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello, World!'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.title()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "scrolled": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hellx, wxrld!'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.replace('o', 'x')" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.find('or')" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "13" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'HELLO, WORLD!'" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"Hello, world!\".upper()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "We can have access to single characters or substrings:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "hi_folk = \"Hi, folk!\"\n", + "# 012345678 " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'H'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'f'" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[4]" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'!'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "hi_folk = \"Hi, folk!\"\n", + "# 012345678 " + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "', folk!'" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[2:]" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hi,'" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "', f'" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hi_folk[2:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "Interestingly, strings cannot be modified:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'str' object does not support item assignment", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-41-4010d49c126f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mhi_folk\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'X'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: 'str' object does not support item assignment" + ] + } + ], + "source": [ + "hi_folk[1] = 'X'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "Often we are faced with the need of splitting strings in tokens:" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['alpha', 'beta', 'gamma']" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = \"alpha:beta:gamma\"\n", + "s.split(\":\")" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'alpha:beta:gamma'" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "':'.join(['alpha', 'beta', 'gamma'])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "Some times we need to remove leading or trailing characters:" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'alpha beta\\tgamma'" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = \" \\t\\n alpha beta\\tgamma \"\n", + "s.strip()" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'alpha beta\\tgamma '" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.lstrip()" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "' \\t\\n alpha beta\\tgamma'" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.rstrip()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## strings\n", + "\n", + "By default str.strip() remove all the characters of space type (' ', '\\t', '\\n'); it can also \n", + "receive the characters to remove:" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'bbbccc'" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = \"aaabbbccc\"\n", + "s.strip(\"a\") # try stripping also \"b\", \"c\", and \"ab\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## bool \n", + "\n", + "The bool type is used for logical values True/False.\n", + "\n", + "Thus, a bool object can assume either one of: \n", + "valori:\n", + "* `True`\n", + "* `False`\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## None\n", + "\n", + "In python exists a special object called None. It is used as an indefinite value (or no value). It is not a type, but an object!" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "a = None\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## python program file\n", + "\n", + "\n", + "<pre>\n", + "#!/usr/bin/env python3\n", + "\n", + "# this is a useless comment\n", + "a = 10 # this is an inline comment\n", + "print(a)\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python program file\n", + "\n", + "Let us analyze the content:\n", + "* The first line\n", + " ```\n", + " #!/usr/bin/env python3\n", + " ```\n", + " It is nothing more than a comment but instructs the Unix shell that will be used the interpreter python3 to run the program. The trick /usr/bin/env is to avoid worrying about the exact path of the python installation, indeed the env command is able to find it.\n", + "\n", + "* It must be the first line of the file.\n", + "* The file name is arbitrary (not necessarily have to end in .py).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python program file\n", + "Let us analyze the content:\n", + "* The line\n", + " ```\n", + " # this is a useless comment\n", + " ```\n", + " is a comment, and it is ignored. \n", + "* Also the next line contains an inline comment. All that is after a # until the end of the line is not interpreted.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## source encoding\n", + "* The python code can be written in any system of characters. By default, if you do not declare anything, it is utf-8.\n", + "* But it can be anything, even Chinese." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "* In python2 the default encoding is latin1, and it is nothing but ASCII characters. Accented letters, for example, are not allowed, not even in the comments.\n", + "* To change the encoding is used a line like this at the beginning of the file:\n", + "```\n", + "# -*- coding: utf-8 -*-\n", + "```\n", + "(PEP 0263)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (name.py)\n", + "* Define a string name that contains your name, a string surname containing your last name;\n", + "* Print the length of the two strings;\n", + "* Concatenate the two strings forming name_surname;\n", + "* Print the length of name_surname.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## containers\n", + "One of the strengths of python is the availability of the containers, which are very efficient, comfortable to use, and versatile:\n", + "* tuple ()\n", + "* list []\n", + "* dict {}\n", + "* set {}, frozenset\n", + "* other containers in collections module\n", + " * OrderedDict, Counter, defaultdict...\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## tuples\n", + "A tuple is an __ordered__ sequence, __immutable__, of values, in arbitrary number and arbitrary type." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 4, 5)" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = (3, 4, 5)\n", + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a[1] # indexes from 0 to len-1" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 3)" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b = 2,3 # without brackets!\n", + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "They are not necessarily homogeneous:" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, (3+4j), 'alfa', (2, 3))" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = (3 + 4j)\n", + "c = (4, z, \"alfa\", b)\n", + "c" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "They can also be on the left of the equal sign:" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3+4j)" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3.0, 4.0)" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r, i = z.real, z.imag\n", + "r, i" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(33, 1)" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d, m = divmod(100, 3)\n", + "d, m" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "They define other operations" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "a = (1, 2, 3)\n", + "b = (4, 5, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "- Concatenation" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 2, 3, 4, 5, 6)" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "- Reiteration" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 2, 3, 1, 2, 3, 1, 2, 3)" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a * 3 " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "The brackets are not required (almost never); but the comma is important!" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "int" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = 1\n", + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tuple" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y = 1,\n", + "type(y)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1,)" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "The brackets are only necessary to define the empty tuple:" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "()" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "empty = ()\n", + "empty" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Slicing gives you access to \"portions\" of a tuple:" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 1, 2, 3, 4)" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = (0, 1, 2, 3, 4)\n", + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 2)" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a[1:3] # from the second element INCLUDED to the fourth EXCLUDED" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 1)" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a[:2] # from the first INCLUDED to the third EXCLUDED" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 3, 4)" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a[2:] # from the third INCLUDED to the last EXCLUDED" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 3, 4, 0, 1)" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a[2:] + a[:2]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Tuples can not be changed, like strings:" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "t = (1, 2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'tuple' object does not support item assignment", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-68-29b3302c4f70>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" + ] + } + ], + "source": [ + "t[0] = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (name.py)\n", + "\n", + "* Starting from the file _name.py_, define a tuple containing your name, your last name, and year of birth.\n", + "\n", + "* Build, starting from the previous one, a new tuple containing, in order, year of birth, name, last name).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## lists\n", + "\n", + "A list is an __ordered__ sequence, __mutable__ of arbitrary values in arbitrary number.\n", + "\n", + "In practice they are mutable tuples.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3]" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [1, 2, 3]\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4]" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.append(4)\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 'XYZ', 3, 4]" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.insert(2, \"XYZ\")\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "As with tuples, you can \"slice\" lists" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 'XYZ', 3, 4]" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[0] # not a container" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[-1] # not a container" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2]" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 'XYZ', 3, 4]" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[-4:]" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, (3, 2, 1, 0), 'XYZ', 3, 4]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[1] = 3, 2, 1, 0\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Some of the functioncs that operate on lists" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 5, 7, 11, 13, 2]" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [3, 5, 7, 9, 11, 13]\n", + "l.append(2)\n", + "l.remove(9)\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 3, 5, 7, 11, 13]" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.sort()\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 11, 7, 5, 3, 2]" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.reverse()\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Lists can be used as stacks:" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 11, 7, 5, 3, 2]" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.pop()" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.pop()" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 11, 7, 5]" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 11, 7, 5, 13, 11, 7, 5]" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l *= 2\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "items assignment " + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 'a', 'b', 'c', 13, 11, 7, 5]" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l[1:4] = ['a', 'b', 'c']\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 88, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.count(13) # try also l.count('z')" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.index('c')" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[13, 'a', 'b', 'c', 13, 11, 7, 5, 2, 3, 5]" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.extend( (2,3,5) )\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 2, 3, 5]" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "del l[:-4]\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "\n", + "Define a list containing the names of some books that you read.\n", + "\n", + "Add few more items to the list.\n", + "\n", + "Print the number of items in the list.Sort the list." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## range\n", + "\n", + "Range is a function to build sequences of integers:" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "range(0, 4)" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "range(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2, 3]" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(4))\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 4, 5, 6]" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(range(3, 7))" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 5, 7, 9]" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(range(3, 10, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## range\n", + "\n", + "Actually range does not build a list or a tuple, but a sequence, that is an object iterable in a given direction.\n", + "\n", + "Basically, range returns an object that you can scroll from the first to the last element, one element after another, always in the same direction.\n", + "\n", + "From this object you can build a container, such as a list or a tuple.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "\n", + "In python2 the range(...) function has the same interface we've seen, but returns a list.\n", + "\n", + "Instead the xrange(...) function behaves exactly like the range in python3." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## extended slices\n", + "\n", + "Slicing syntax also accepts a stride parameter, always separated by \":\"" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(20))\n", + "l[1:18] \n", + "# try also \n", + "#l[1:18:3]\n", + "#l[1::3]\n", + "#l[:5:3]\n", + "#l[::3]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "stride can also be negative" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[18, 15, 12, 9, 6]" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(20))\n", + "l[18:3:-3] \n", + "# try also \n", + "#l[17:2:-3]\n", + "#l[::-1] " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## extended slices\n", + "\n", + "When you assign with slicing, the extended slices are less flexible than regular slices, in fact the length \n", + "of the operands must be identical:" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['a', 0, 1, 2, 3, 'd']" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(5))\n", + "r = ['a', 'b', 'c', 'd']\n", + "r[1:3] = l[:-1] # len(r[1:3]) == len(l[:-1]), OK\n", + "r" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "attempt to assign sequence of size 3 to extended slice of size 2", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-99-4d9e2228211e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0ml\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# len(r[::2]) != len(l[::2]), KO!!!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mValueError\u001b[0m: attempt to assign sequence of size 3 to extended slice of size 2" + ] + } + ], + "source": [ + "r[::3] = l[::2] # len(r[::2]) != len(l[::2]), KO!!!" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 0, 2, 2, 4, 'd']" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "r[::2] = l[::2] # len(r[::2]) == len(l[::2]), ok\n", + "r" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## extended slices\n", + "When you delete items with slicing, there are no problems:" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 4, 5, 7, 8, 10]" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(11))\n", + "del l[::3]\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 5, 8]" + ] + }, + "execution_count": 102, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "del l[::2]\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## sets\n", + "\n", + "A set is an __unordered__ collection, without duplicates, __mutable__, containing arbitrary values in arbitrary number.\n", + "\n", + "A frozenset is an __unordered__ collection, without duplicates, __immutable__, containing arbitrary values in arbitrary number.\n", + "\n", + "They are not ordered in the sense that the elements are not maintained in a meaningful user order; this because the order used by the interpreter is useful to make fast searching of items.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2, 3, 4}" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = set()\n", + "s.add(2)\n", + "s.add(3)\n", + "s.add(2)\n", + "s.add(4)\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'alfa', 2, 3.5}" + ] + }, + "execution_count": 104, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "u = set(['alfa', 2, 3.5])\n", + "u" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "one can also use the `'{}'`" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'alfa', 2, 3.5}" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "u = {'alfa', 2, 3.5}\n", + "u" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1, 2, 3, 4}" + ] + }, + "execution_count": 106, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l=[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]\n", + "t = set(l)\n", + "t" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2, 3, 4}" + ] + }, + "execution_count": 107, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2, 3, 4}" + ] + }, + "execution_count": 108, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.intersection(t)" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "set()" + ] + }, + "execution_count": 109, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.difference(t) # result in set() not {}!" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1}" + ] + }, + "execution_count": 110, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.difference(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1}" + ] + }, + "execution_count": 111, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.symmetric_difference(t)" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1, 2, 3, 4}" + ] + }, + "execution_count": 112, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.union(t)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2, 4}" + ] + }, + "execution_count": 113, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.discard(3)\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "set()" + ] + }, + "execution_count": 114, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.clear()\n", + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## frozensets\n", + "\n", + "By analogy with the tuples, which can be considered \"frozen lists\", there are also frozensets:" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "frozenset({1, 2, 3, 4})" + ] + }, + "execution_count": 115, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ft = frozenset(t)\n", + "ft" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'frozenset' object has no attribute 'add'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-116-73c54a880fa9>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mft\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'frozenset' object has no attribute 'add'" + ] + } + ], + "source": [ + "ft.add(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (primes_1.py)\n", + "\n", + "With only these data structures:" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "all = set(range(1, 20))\n", + "primes = {1, 2, 3, 5, 7, 11, 13, 17, 19}\n", + "even = {2, 4, 6, 8, 10, 12, 14, 16, 18}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "Print:\n", + "* the set of odd numbers\n", + "* the set of odd prime numbers\n", + "* the set of odd not prime numbers (lower than 20)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## dicts\n", + "A dictionary (dict) is a container that associates an arbitrary and __unique key__ to an arbitrary __value__.\n", + "\n", + "Basically, the keys are handled as a set, but each key is uniquely associated with a value.\n", + "\n", + "In other languages it is known as an associative array or a map.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": { + "scrolled": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'C': 6, 'Fe': 26, 'H': 1, 'He': 2}" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "atomic_number = {'H': 1, 'He': 2, 'C': 6, 'Fe': 26}\n", + "atomic_number" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 119, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "atomic_number['C']" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "They are not necessarily homogeneous:" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'alfa': 3, 2.5: 'xyz', (3+4j): [3, 4, 5], (1, 2, 3): {'x': 2, 'y': 3, 'z': 1}}" + ] + }, + "execution_count": 120, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d = {}\n", + "d['alfa'] = 3\n", + "d[2.5] = 'xyz'\n", + "d[3+4j] = [3, 4, 5]\n", + "d[(1,2,3)] = { 'x': 2, 'y': 3, 'z': 1 }\n", + "d" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['alfa', 2.5, (3+4j), (1, 2, 3)]" + ] + }, + "execution_count": 121, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(d.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[3, 'xyz', [3, 4, 5], {'x': 2, 'y': 3, 'z': 1}]" + ] + }, + "execution_count": 122, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(d.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('alfa', 3),\n", + " (2.5, 'xyz'),\n", + " ((3+4j), [3, 4, 5]),\n", + " ((1, 2, 3), {'x': 2, 'y': 3, 'z': 1})]" + ] + }, + "execution_count": 123, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(d.items())" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 124, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "'alfa' in d # try also 'beta' in d" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 125, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.get('alfa', -1999) # try also d.get('beta', -1999)" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'alfa': 3,\n", + " 2.5: 'xyz',\n", + " (3+4j): [3, 4, 5],\n", + " (1, 2, 3): {'x': 2, 'y': 3, 'z': 1},\n", + " 'beta': -1999}" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.setdefault('alfa', -1999)\n", + "d.setdefault('beta', -1999)\n", + "d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "They can be used as stacks:" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.pop('alfa', -5) # -5 is a default value in case the requiret key is not found\n", + " # try also d.pop('gamma', -5)" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('beta', -1999)" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.popitem()" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{2.5: 'xyz', (3+4j): [3, 4, 5], (1, 2, 3): {'x': 2, 'y': 3, 'z': 1}}" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "updating a dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 1, 'b': 2, 'c': 3, 'd': 4, 1: 1.0, 2: 2.0}" + ] + }, + "execution_count": 130, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d1 = dict(a=1, b=2, c=3, d=4)\n", + "d2 = {1: 1.0, 2: 2.0}\n", + "d1.update(d2)\n", + "d1" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 131, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.clear()\n", + "d" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "\n", + "Define a dictionary that links some of the books that you read with the name of its author.\n", + "\n", + "Print the names of all authors (without duplicates)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## flow control constructs\n", + "Python has few constructs for flow control, according to the philosophy of maximum simplicity.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## indentation\n", + "\n", + "* In python indentation is syntactic, that is it determines the nesting of statements.\n", + "* This is an integral part of the python philosophy: since indenting is good, and since a program without indentation is bad, why do not force to indent?\n", + "* Thus becomes unnecessary to use the curly brackets to enclose blocks, as in C/C++, or statement of closure, as the END of Fortran.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## indentation\n", + "\n", + "How much you should indent? \n", + "\n", + "It is arbitrary, but must be consistent within the block.\n", + "\n", + "Style/common sense rules are:\n", + "* indent always with 4 spaces\n", + "* NEVER use tabs to indent" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## if-elif-else" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a , b = 1 , 2" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "if a == b:\n", + " print(a)\n", + "elif a > b:\n", + " print(b)\n", + "else:\n", + " print(a + b)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop\n", + "\n", + "* The for loop allows you to iterate over \"iterable objects\" as lists, tuples, sets, dicts, range, ..." + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n" + ] + } + ], + "source": [ + "for i in range(3):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "b\n", + "10\n", + "5.5\n" + ] + } + ], + "source": [ + "t = ('a', 'b', 10, 5.5)\n", + "for i in t:\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "b\n", + "c\n" + ] + } + ], + "source": [ + "d = {'a': 0, 'b': 1, 'c': 2}\n", + "for key in d.keys():\n", + " print(key)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n" + ] + } + ], + "source": [ + "for val in d.values():\n", + " print(val)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a = 0\n", + "b = 1\n", + "c = 2\n" + ] + } + ], + "source": [ + "for key, val in d.items():\n", + " print(key, '=', val)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "b\n", + "c\n" + ] + } + ], + "source": [ + "for key in d:\n", + " print(key)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "None\n", + "2\n" + ] + } + ], + "source": [ + "for key in ('a', 'd', 'c'):\n", + " print(d.get(key, None))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{0, 2, 3, 4, 6, 8, 9}" + ] + }, + "execution_count": 153, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = set(list(range(0, 10, 2))+list(range(0, 10, 3)))\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "2\n", + "3\n", + "4\n", + "6\n", + "8\n", + "9\n" + ] + } + ], + "source": [ + "for i in s:\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## for & range\n", + "The use of for and range allows us to understand the difference between \n", + "containers (such as lists, tuples, sets, dicts) and iterables (as range). For \n", + "example:\n", + "\n", + "<pre>\n", + ">>> for i in range(1000000000000000000000):\n", + "... if i < 3: \n", + "... print(i)\n", + "... \n", + "0\n", + "1\n", + "2\n", + "...... # please, be patient! \n", + "</pre>\n", + "\n", + "If it was a list or a tuple I would not have enough memory available to build this object!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## if/for body\n", + "The indentation has a side effect: there must be at least one statement. \n", + "\n", + "Then:" + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "unexpected EOF while parsing (<ipython-input-155-0e5327973a24>, line 2)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"<ipython-input-155-0e5327973a24>\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m # nothing to do\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m unexpected EOF while parsing\n" + ] + } + ], + "source": [ + "if a > 10:\n", + " # nothing to do" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## pass\n", + "\n", + "In these situations you can use the special statement **pass**, which does nothing:" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "if a > 10:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## if/for body, single statement\n", + "\n", + "If the body of the `if/for` block contains a single statement, this can be written on the same line:" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "if a > 10: pass" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "Nothing changes; better avoid that." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "\n", + "Starting from the dictionary “book : authorâ€, write the code for printing, for each author, the number of books in the dictionary.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## while\n", + "\n", + "The while loop is the generic loop with one condition:" + ] + }, + { + "cell_type": "code", + "execution_count": 158, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "i = 0\n", + "while i < 4:\n", + " print(i)\n", + " i += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## while\n", + "\n", + "However, the previous loop is not a good example of programming, because we emulated a for loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "for i in range(4):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## while\n", + "\n", + "The while loop is appropriate when you have an arbitrary condition and no iteration:\n", + "\n", + "```python\n", + "while error > tolerance:\n", + " result, error = compute(result)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## break\n", + "\n", + "Break allows you to exit the loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n" + ] + } + ], + "source": [ + "for i in range(10000):\n", + " print(i)\n", + " if i%3 == 2:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## while and break\n", + "\n", + "Often it is used while to build seemingly endless loop, from which it actually exits with a break:\n", + "\n", + "```python\n", + "while True:\n", + " result, error = compute(result)\n", + " if error < tolerance:\n", + " break\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## continue\n", + "\n", + "Continue allows you to go to the next iteration:" + ] + }, + { + "cell_type": "code", + "execution_count": 161, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "for i in range(4):\n", + " if i == 1:\n", + " continue\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## loops: else clause\n", + "The loops (for and while) can have an else clause, which is executed only if the loop completes naturally (for example, if you do not exit the loop with a break):" + ] + }, + { + "cell_type": "code", + "execution_count": 162, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "for i in range(10):\n", + " if i > 3: break\n", + " print(i)\n", + "else:\n", + " print(\"finished!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 163, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "finished!\n" + ] + } + ], + "source": [ + "for i in range(2):\n", + " if i > 3: break\n", + " print(i)\n", + "else:\n", + " print(\"finished!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## switch\n", + "Ther is no construct like a C `switch` or a Fortran select, just use a series of blocks if-elif-else.\n", + "\n", + "If you have no idea about what the `switch` or select are, you can safely ignore this slide...\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## operators\n", + "There are several operators:\n", + "* Comparison operators: ==, !=, <, <=, >, >=, is, in\n", + "* Logical operators: and, or, not\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## comparisons" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 164, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1 > 5" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 165, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b = 1 <= 5\n", + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## in\n", + "\n", + "The expression `a in obj` returns `True` if the object a is content in the object obj. Not all objects contain something; for example obj may be a list, a tuple, a set or a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 166, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lst = [3, 5, 7]\n", + "2 in lst" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## in\n", + "If the right operand does not allow the operation you receive an error:" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "argument of type 'int' is not iterable", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-167-a0c8fa4b4d67>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: argument of type 'int' is not iterable" + ] + } + ], + "source": [ + "a in 10" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## is\n", + "\n", + "The expression `a == b` returns `True` if the value of a is identical to the value of b.\n", + "\n", + "The expresson `a is b` returns `True` if a and b refer to the same physical object:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, False)" + ] + }, + "execution_count": 168, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l1 = [1, 3, 8]\n", + "l2 = [1, 3, 8]\n", + "l3 = l1\n", + "l1 == l2, l1 is l2" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, True)" + ] + }, + "execution_count": 169, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l1 == l3, l1 is l3" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, False)" + ] + }, + "execution_count": 170, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l2 == l3, l2 is l3" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## object reference\n", + "It is time to mention the true meaning of an expression like \n", + "\n", + "<pre>\n", + ">>> a = b\n", + "</pre>\n", + "\n", + "Any object is b, this expression does nothing but define a new symbolic name a for the same object.\n", + "\n", + "It is similar to a link or an alias; Technically, it is called object reference." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## object reference\n", + "\n", + "So, when we write\n", + "\n", + "<pre>\n", + ">>> a = b\n", + "</pre>\n", + "\n", + "nothing is copied. It follows that a and b are the same object:\n", + "\n", + "<pre>\n", + ">>> a is b\n", + "True\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## conversion to bool\n", + "\n", + "The built-in types are automatically converted to bools, for example they can be directly used in conditional expressions. The rules are:\n", + "\n", + "* An `int` equal to 0 is equivalent to False, otherwise `True`\n", + "* A `float` equal to 0.0 is equivalent to False, otherwise `True`\n", + "* An empty string \"\" is equivalent to False, otherwise `True`\n", + "* An empty container (`[]`, `()`, `set()`, `{}`, ...) is equivalent to False, otherwise `True`\n", + "* `None` is equivalent to `False`\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (divisors.py)\n", + "\n", + "Write a code to print all prime divisors of the number 2009\n" + ] + } + ], + "metadata": { + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/02-Introduction_to_Python.ipynb b/02-Introduction_to_Python.ipynb new file mode 100644 index 0000000..ee7fb45 --- /dev/null +++ b/02-Introduction_to_Python.ipynb @@ -0,0 +1,3413 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions\n", + "\n", + "* A function is declared with `def`, followed by the function name and the parameter list; the body of the function is indented.\n", + "\n", + "* You do not have to declare the type of arguments and of the return value." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def summa(a, b):\n", + " return a + b # function body" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7.2" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa(3.2, 4) # works with int and float, \n", + " # try also summa(3.2, 9.1)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello, world!'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa(\"Hello, \", \"world!\") # works with strings " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa([1, 2], [3, 4, 5]) # lists" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions\n", + "\n", + "If the function receives parameters of incorrect type, you will have a run-time error:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "unsupported operand type(s) for +: 'int' and 'str'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-5-415ee3ec4b29>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msumma\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'ccc'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m<ipython-input-1-f411e876abaf>\u001b[0m in \u001b[0;36msumma\u001b[0;34m(a, b)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0msumma\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\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[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mb\u001b[0m \u001b[0;31m# function body\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'str'" + ] + } + ], + "source": [ + "summa(6, 'ccc')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions\n", + "\n", + "Functions can be recursive:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " if n < 2:\n", + " return 1\n", + " else:\n", + " return n * factorial(n - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "1\n", + "120\n", + "3628800\n", + "788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000\n" + ] + } + ], + "source": [ + "for i in (0, 1, 5, 10, 200):\n", + " print(factorial(i))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions\n", + "\n", + "Any function has a return value. By default, this value is `None`. If you want to give a specific return value, for example 4, just add the statement `return` 4.\n", + "\n", + "A `return` statement without expression to the right is equivalent to return None.\n", + "\n", + "If a function ends without having encountered any `return`, implicitly it executes a `return None`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (divisors.py)\n", + "* Write a function that determines all the divisors of an arbitrary integer\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "## test (divisors.py -> primes.py)\n", + "* Write a function that checks whether a number is prime (no matters if not efficient!)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## arguments passing\n", + "The arguments of a function can be passed by __position__ or by __name__:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "def count(lst, val):\n", + " c = 0\n", + " for el in lst:\n", + " if el == val: \n", + " c += 1\n", + " return c" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "count([1,2,1,3,2,4], 2) # passing args by position" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "count(val=2, lst=[1,2,1,3,2,4]) # passing args by name" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## arguments passing\n", + "After passing at least an argument by name, you can not to pass the nexts by position:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "positional argument follows keyword argument (<ipython-input-11-c888420936d4>, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"<ipython-input-11-c888420936d4>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m count(val=2, [1,2,1,3,2,4,1])\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n" + ] + } + ], + "source": [ + "count(val=2, [1,2,1,3,2,4,1])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## default arguments\n", + "The arguments of a function can have default values; in this case, in the function call they can be omitted:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "# argument \"val\" now has a default value\n", + "def count(lst, val=1):\n", + " c = 0\n", + " for el in lst:\n", + " if el == val: \n", + " c += 1\n", + " return c" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + " count([1,2,1,3,2,4,1]) # -> count([1,2,1,3,2,4,1], 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## default arguments\n", + "If an argument accepts a default value, also all next arguments must have a default value:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "non-default argument follows default argument (<ipython-input-14-6ad44fe60a1c>, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"<ipython-input-14-6ad44fe60a1c>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m def f(a, b=0, c):\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m non-default argument follows default argument\n" + ] + } + ], + "source": [ + "def f(a, b=0, c):\n", + " print(a+b)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## arbitrary argument list\n", + "A function can have arbitrary positional arguments; these arguments are placed in a tuple:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def f(a, *args):\n", + " print(a)\n", + " print(args)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "()\n" + ] + } + ], + "source": [ + "f(\"a\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "(2, 5, 'y')\n" + ] + } + ], + "source": [ + "f(\"a\", 2, 5, 'y')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## arbitrary argument list\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def summa(a, *args):\n", + " for i in args: \n", + " a += i\n", + " return a" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "111" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa(10, 1, 100)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'abcd'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa(\"a\", \"bc\", \"d\")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa([1], [], [2, 3], [4, 5, 6])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## arbitrary keyword arguments\n", + "Arbitrary arguments can be passed even by name; in such case, they are maintained in a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def g(a, **kwargs):\n", + " print(a)\n", + " print(kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "{'y': 9, 'z': 5, 'x': 1}\n" + ] + } + ], + "source": [ + "g(5, y=9, z=5, x=1) # kwargs are put on a dictionary" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## keyword-only arguments\n", + "\n", + "A function can have keyword-only arguments that can not be passed positionally, but must always be passed by name.\n", + "\n", + "They are positioned between `*args` and `**kwargs`; They can have a default. \n", + "\n", + "If the function does not need to args, you can leave an `*` (???)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## keyword-only arguments" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def foo(a, *, kwonly):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "foo() missing 1 required keyword-only argument: 'kwonly'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-28-2a3bb2b3f42e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfoo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# try also foo(10, 5)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: foo() missing 1 required keyword-only argument: 'kwonly'" + ] + } + ], + "source": [ + "foo(10) # try also foo(10, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "foo(10, kwonly=5)\n", + "foo(kwonly=5, a=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "KeywordÂonly arguments are not supported in python2." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## general form of a function\n", + "To summarize, the general form of a function is:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def foo(a, b=0, *args, kwonly0, kwonly1=10, **kwargs):\n", + " print(a, b, args, kwonly0, kwonly1, kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 0 () 999 10 {}\n" + ] + } + ], + "source": [ + "foo(2, kwonly0=999)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 3 (4, 5, 6, 7) 999 10 {'x': 10.0, 'y': 20.0, 'z': 30.0}\n" + ] + } + ], + "source": [ + "foo(2, 3, 4, 5, 6, 7, x=10.0, y=20.0, z=30.0, kwonly0=999)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## unpacking argument list\n", + "Sometimes it may happen to have, in a list or a tuple, the values of the arguments that we want to pass positionally to a function:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def f(a, b, c):\n", + " return a*b-c" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "17\n" + ] + } + ], + "source": [ + "args = [3, 5, -2]\n", + "print(f(*args)) ### => f(3, 5, -2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## unpacking keyword arguments\n", + "Sometimes it may happen to have, in a dictionary, the arguments to be passed to a function by name:" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def f(x, y, z):\n", + " return x**2 + y**2 - z" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20\n" + ] + } + ], + "source": [ + "kwargs = {'x': 3, 'z': 5, 'y': 4}\n", + "print(f(**kwargs)) ### => f(x=3, y=4, z=5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## doc string\n", + "You can attach a `doc string` to a function. A `doc string` is an arbitrary string of documentation for the function. The string becomes part of the function; if the name of the function is __foo__, `foo.__doc__` is its `doc string`.\n", + "\n", + "The `doc string` is a python string placed directly after the `def` line.\n", + "\n", + "By default, the `doc string` value is `None`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## doc string" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def summa(a, b, *args):\n", + " \"\"\"Returns the sum of two or more numbers:\n", + " >>> print(summa(2, 4, 10, 20, 30))\n", + " 66\n", + " >>>\"\"\"\n", + " result = a + b\n", + " for i in args:\n", + " result += i\n", + " return result" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Returns the sum of two or more numbers:\n", + " >>> print(summa(2, 4, 10, 20, 30))\n", + " 66\n", + " >>>\n" + ] + } + ], + "source": [ + "print(summa.__doc__)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## doc string\n", + "Built-in functions have a doc string, that can help us understand how to use them through the interpreter in interactive:" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "range(stop) -> range object\n", + "range(start, stop[, step]) -> range object\n", + "\n", + "Return an object that produces a sequence of integers from start (inclusive)\n", + "to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n", + "start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n", + "These are exactly the valid indices for a list of 4 elements.\n", + "When step is given, it specifies the increment (or decrement).\n" + ] + } + ], + "source": [ + "print(range.__doc__) " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## everything is an object\n", + "In Python everything is an object, even a function. Therefore, we can associate symbolic names even to the functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "22" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def summa(a, b):\n", + " return a + b\n", + "\n", + "somma = summa\n", + "somma(10, 12)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functions as arguments of functions\n", + "Since you can assign a symbolic name to a function, you can even pass a function as an argument to another function:" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def summa(a, b): return a+b\n", + "def sub(a, b): return a-b\n", + "def g(x, f): return f(x, x+1)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g(1, summa)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-1" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g(1, sub)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## sort\n", + "A good example of a function that takes a function as an argument is the sorting of lists.\n", + "\n", + "The method `sort` of list, that we have seen, can receive an optional parameter keyword-only type function. If this parameter is supplied, it must be a function of one argument that, given a list item, returns the key to sort by." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "lst = [20, 10, 30]\n", + "def f(x): \n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[10, 20, 30]" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lst.sort(key=f) # WARNING: key is a keyword-only argument, \n", + " # it can not be passed by position\n", + "lst" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[30, 10, 20]" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def g(x):\n", + " return x % 3\n", + "\n", + "lst.sort(key=g)\n", + "lst" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## sort\n", + "\n", + "Let's see in detail the latest example to understand how it works:\n", + "\n", + "```python\n", + ">>> lst = [10, 20, 30]\n", + ">>> def g(x):\n", + "... return x % 3 \n", + "... \n", + ">>> lst.sort(key=g) # lst: [10, 20, 30]\n", + ">>> lst # keys: [10%3, 20%3, 30%3] == [1, 2, 0] \n", + "[30, 10, 20] # tmp: [(10, 1), (20, 2), (30, 0)]\n", + ">>> # stmp: [(30, 0), (10, 1), (20, 2)] \n", + " # sorted_lst: [30, 20, 10]\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## sort" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(2, -3, 6), (10, 0, 4), (1, 2, 2), (-1, 9, 1)]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [(1, 2, 2), (-1, 9, 1), (10, 0, 4), (2, -3, 6)]\n", + "\n", + "def getkey1(x): \n", + " return x[1]\n", + "\n", + "l.sort(key=getkey1)\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(-1, 9, 1), (1, 2, 2), (2, -3, 6), (10, 0, 4)]" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def getkey2(x):\n", + " return x[0]-x[1]\n", + "\n", + "l.sort(key=getkey2)\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "* As seen above it works also in python2.\n", + "* But in this case we must be careful, because list.sort in python2 accepts positionally a function of a different type, which takes two arguments. So be careful to always use `key=...` also in python2!\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## lambda functions\n", + "\n", + "Within the functional programming paradigm, for which python provides a dicent support, it is often necessary to define small functions to be passed as an argument to other functions.\n", + "\n", + "Lambda functions are \"anonymous\" funxtions made in a single line, simple and compact.\n", + "\n", + "They have some limitations: they can return a result of a single expression, whatever complexity. They can not execute a statement (like a=10).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## lambda functions" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[30, 10, 20]" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lst = [10, 20, 30]\n", + "lst.sort(key=lambda x: x % 3) # \"arguments\" : \"return value\"\n", + "lst" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## lambda functions" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(2, -3), (10, 0), (1, 2), (-1, 9)]" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [(1, 2), (-1, 9), (10, 0), (2, -3)] \n", + "l.sort(key=lambda x: x[1]) # argument=x, return value = x[1]\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(-1, 9), (1, 2), (2, -3), (10, 0)]" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l.sort(key=lambda x: x[0]-x[1]) # argument=x, return value = x[0]-x[1]\n", + "l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## lambda functions\n", + "Lambda may receive arguments in the same way as \"normal\" functions:\n", + "\n", + "<pre>\n", + "lambda a, b=0, *args, kwonly0, kwonly1=None, **kwargs: ...\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## lambda functions\n", + "Lambda functions do not necessarily have a name, but since everything is an object, and since a name can be assigned to any object, you can do his with the lambda:" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "summa = lambda x, y: x + y\n", + "summa(3, 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## sequences\n", + "A sequence is any iterable object.\n", + "\n", + "The containers that we saw are iterable, therefore they are sequences. But the reverse is not true: a sequence is not necessarily a container.\n", + "\n", + "For example `range(0, 1000000000)` do not contain1000000000 elemens, but it generates them one after the other, from left (0) to right (1000000000 excluded)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functional programming\n", + "\n", + "The functional programming paradigm is based primarily on the application of functions on sequences." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functional programming\n", + "The functional programming paradigm is based mainly on two built-in functions:\n", + "\n", + "* `filter`: applies a filter to a sequence\n", + "* `map`: apply a function to all elements of a sequence\n", + "\n", + "Warning: they return iterables, not lists or tuples." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## filter\n", + "The function `filter(cond, seq)` returns a sequence of all the elements of `seq` that satisfy the condition `cond`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 5, 10, 15, 20, 25]" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(30))\n", + "list(filter(lambda x: x%5 == 0, l))" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2]" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(filter(lambda x: x < 3, l))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## map\n", + "The function `map(function, sequence)` returns a sequence of length equal to `sequence`, whose \n", + "elements are obtained by applying the `function` to every element of `sequence`." + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = list(range(10))\n", + "list(map(lambda x: x**2, l))" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(map(lambda x: x+100, l))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## functools.reduce\n", + "\n", + "There is a third type of function `functools.reduce(function, sequence)` (contained in the `functools` module) that performs the reduction operation: `sequence` is associated to a scalar, obtained by repeatedly applying the `function` to the elements of `sequence`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "\n", + "In python2 filter and map functions always returnlists, not sequences. \n", + "\n", + "Moreover, `reduce` is a built-in function (therefore you do not need to import any module). It was moved into `functools` module because it is rarely used.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## sum, min, max\n", + "They are reduction functions to obtain the sum, the minimum and the maximum of a sequence of elements:" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "45" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = range(10)\n", + "sum(l)" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(l)" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "* Starting from the dictionary “book: authorâ€, build a list of all the books whose title does not contain the character \"a\".\n", + "\n", + "* Starting from the dictionary “book: authorâ€, build a list of all the books, sorted by author name" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## list comprehension\n", + "Is called `list comprehension` the ability to perform complex operations in a single expression on the lists." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = range(10)\n", + "[i+1 for i in l]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 9, 36, 81]" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[i**2 for i in l if i%3==0]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## list comprehension\n", + "\n", + "Creating a \"matrix\" 7x10:" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[[0 for i in range(10)] for i in range(7)]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## list comprehension\n", + "Cartesian product or combinations:" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "scrolled": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(1, 'a', 9),\n", + " (1, 'a', 8),\n", + " (1, 'a', 7),\n", + " (1, 'b', 9),\n", + " (1, 'b', 8),\n", + " (1, 'b', 7),\n", + " (2, 'a', 9),\n", + " (2, 'a', 8),\n", + " (2, 'a', 7),\n", + " (2, 'b', 9),\n", + " (2, 'b', 8),\n", + " (2, 'b', 7),\n", + " (4, 'a', 9),\n", + " (4, 'a', 8),\n", + " (4, 'a', 7),\n", + " (4, 'b', 9),\n", + " (4, 'b', 8),\n", + " (4, 'b', 7)]" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l1 = [1, 2, 4]\n", + "l2 = ['a', 'b']\n", + "l3 = [9, 8, 7]\n", + "[(e1,e2,e3) for e1 in l1 for e2 in l2 for e3 in l3]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "Starting from the dictionary “book: authorâ€, build a list of all the books whose title does not contain the character \"a\" using the list comprehension.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "There are two functions to convert an object to a string: `str` e `repr`.\n", + "\n", + "The call to `str(x)` is equivalent to `x.__str__()` if the object `x` has a metod `__str__`, otherwise `x.__repr__()` is called. \n", + "\n", + "All objects have automatically a metod `__repr__`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "When an object is printed, for example,\n", + "\n", + "```python\n", + ">>> print(x)\n", + "```\n", + "\n", + "the object will be converted to a string; this occurs through `str`, therefore is equivalent to this:\n", + "\n", + "```python\n", + ">>> print(str(x))\n", + "```\n", + "\n", + "i.e. will be printed the result of `x.__str__` if `x` has a metod `__str__`, `x.__repr__` otherwise." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "We can force the use of str or repr; with strings it is possible to see the difference:" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, world!\n" + ] + } + ], + "source": [ + "a = \"Hello, world!\"\n", + "print(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, world!\n" + ] + } + ], + "source": [ + "print(str(a))" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Hello, world!'\n" + ] + } + ], + "source": [ + "print(repr(a))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "Printing a standard container (lists, tuples, dictionaries or sets), the elements are always printed by repr:" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, world!\n" + ] + } + ], + "source": [ + "print(a) # str(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Hello, world!']\n" + ] + } + ], + "source": [ + "print([a]) # repr(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "In practice, `repr` should return a representation of the object closest to the one \"internal\". For built-in types, the output of `repr` is equivalent to a literal constant that defines an equivalent object:" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hello\n" + ] + } + ], + "source": [ + "a = 'hello'\n", + "print(str(a))" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'hello'\n" + ] + } + ], + "source": [ + "print(repr(a))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "Now we know what happens when we write an expression in the interactive mode: the result is printed with `repr` and not with `str`:" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'hello'" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = 'hello'\n", + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## str and repr\n", + "\n", + "In practice repr is used in contexts where it is good to avoid ambiguity with respect to the representation; for example withstrings:" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "51" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "11 + 40" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'51'" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "'5' + '1'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "If it were used str in place of repr, in both cases the output would be the same!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## string formatting\n", + "\n", + "Python supports two modes of string formatting, one old and one new.\n", + "\n", + "Although the new is better and highly recommended, it is necessary to know both, because the old is still widely used.\n", + "\n", + "Even python2 (> 2.6) implements the new mode.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## string formatting\n", + "String formatting is used to replace portions of a string with the value of the generic type, getting a new string.\n", + "\n", + "Normally it is used to format program output by printingtext and numerical information; for example:\n", + "\n", + "<pre>\n", + "$ my_wonderful_program 5 10\n", + "The result of expression 5 + 10 is 15.\n", + "$\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “old-style†string formatting\n", + "The oldest mode is similar to that used for the C `printf` function." + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'The result for 5 + 10 is 15'" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a, b = 5, 10\n", + "\"The result for %d + %d is %d\" % (a, b, a+b)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'The result for 0.100 + 002 is +2'" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a, b = 0.1, 2\n", + "\"The result for %.3f + %03d is %+d\" % (a, b, a+b)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “old-style†string formatting\n", + "The association between format specifiers and parameters can also be done by name:" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'10 + 20 + 30'" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dct = {\n", + " 'a': 10,\n", + " 'b': 20,\n", + " 'c': 30,\n", + "}\n", + "\"%(a)d + %(b)d + %(c)d\" % dct" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “old-style†string formatting\n", + "Unlike the C `printf`, the format specifier `%s` can be used for any value, because it uses the conversion to string through `str()`:" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10, ciao, 5.4\n" + ] + } + ], + "source": [ + "a, b, c = 10, \"ciao\", 5.4\n", + "print(\"%s, %s, %s\" % (a, b, c))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "It uses string's method `format()`." + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My name is James Bond.'" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My name is {0} {1}.\".format(\"James\", \"Bond\")" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My name is Bond James.'" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My name is {1} {0}.\".format(\"James\", \"Bond\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "If you want to maintain the order of positional arguments of format, like in the first example, you can omit the index:" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My name is James Bond.'" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My name is {} {}.\".format(\"James\", \"Bond\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "\n", + "You can refer to the name of the format arguments passing them by name:" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My Name is James Bond.'" + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My Name is {name} {surname}.\".format(surname=\"Bond\", name=\"James\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "\n", + "Of course you can print twice the same argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My name is Bond. James Bond.'" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My name is {1}. {0} {1}.\".format(\"James\", \"Bond\")" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'My name is Bond. James Bond.'" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"My name is {s}. {n} {s}.\".format(n=\"James\", s=\"Bond\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "\n", + "You can access at the elements of a list:" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'two + one + zero + four = seven'" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lst = [\"zero\", \"one\", \"two\", \"three\", \"four\", \"five\",\"six\", \"seven\", \"eight\", \"nine\", \"ten\"]\n", + "\n", + "\"{a[2]} + {a[1]} + {a[0]} + {a[4]} = {a[7]}\".format(a=lst)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "It is possible to access at the elements in a dictionary:" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'0, 2'" + ] + }, + "execution_count": 88, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abc = {'a': 0, 'b':1, 'c':2}\n", + "\n", + "\"{d[a]}, {d[c]}\".format(d=abc)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "\n", + "You can specify the format in which to print:" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'10 / 3 = 3.33'" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"{0:d} / {1:d} = {2:.2f}\".format(10, 3, 10 / 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "Format specifications are very similar to those of the old-style formatting." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## “new-style†string formatting\n", + "It is possible also specify whether an item should be converted to string with `str` or `repr`:" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "abc : 'abc'\n" + ] + } + ], + "source": [ + "print(\"{0!s} : {0!r}\".format(\"abc\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (books.py)\n", + "* Print the entire contents of the dictionary “book: author†with a format similar to this:\n", + "* Umberto Eco wrote the book 'Il nome della rosa'.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## class (short introduction)\n", + "The classes are the means to define new types. Imagine to not have type complex:" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "class Complex(object):\n", + " def __init__(self, r=0.0, i=0.0):\n", + " self.re = r\n", + " self.im = i\n", + " def __mul__(self, other):\n", + " return Complex(self.re*other.re-self.im*other.im, \n", + " self.re*other.im+self.im*other.re)\n", + " def __imul__(self, other):\n", + " self.re = self.re*other.re-self.im*other.im\n", + " self.im = self.re*other.im+self.im*other.re\n", + " return self\n", + " def __rmul__(self, other):\n", + " return self.__mul__(other)\n", + " def __str__(self):\n", + " return \"({0}+{1}j)\".format(self.re, self.im)" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2+3j)\n" + ] + } + ], + "source": [ + "ci = Complex(r=2, i=3)\n", + "print(ci)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## instances\n", + "We said that everything is an object. Now we can say that an object is an instance of a class. \n", + "\n", + "4 is an instance of the class `int`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## methods\n", + "Classes have methods or functions that can be attached to instances of that class.\n", + "\n", + "The first argument to any method is the instance on which it applies; conventionally it is called self." + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A:f 10\n" + ] + } + ], + "source": [ + "class A(object):\n", + " def f(self, i):\n", + " print(\"A:f\", i)\n", + "\n", + "a = A()\n", + "a.f(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## attributes\n", + "Each instance (each object) can have attributes. They can be added at any time:" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'A' object has no attribute 'x'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-94-a969ed79e4a3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'A' object has no attribute 'x'" + ] + } + ], + "source": [ + "a.x" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "a.x = 10.2" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10.2" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.x" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## attributes\n", + "Normally however the attributes should be defined only by the methods of the class. In particular, through the `__init__` method, the class constructor, which is called when an instance of a class is being built.\n", + "\n", + "```python\n", + "class Complex(object): \n", + " def __init__(self, r=0.0, i=0.0):\n", + " self.re = r # add attribute 're' to self\n", + " self.im = i # add attribute 'im' to self\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## attributes\n", + "In other words, the attributes of an instance of a certain class should be defined within the class, and in particular in the `__init__` method, and not outside.\n", + "\n", + "But this is a style rule, not a syntax rule." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## special attributes\n", + "\n", + "All classes have the attribute `__init__`, because instances must be able to be built. Similarly, there \n", + "will be a `__del__`, the destructor, called automatically when the object should be destroyed.\n", + "\n", + "For various functionality there are methods with special name, for example: `__len__, __str__, __repr__, __sort__, __get__, __setitem__, __delitem__, __add__, __iadd__, __radd__, __contains__, ...`" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## class attributes\n", + "\n", + "Classes themselves may have attributes. The methods are attributes of the class, type function." + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "class ALFA(object):\n", + " A = 10 # class attribute\n", + " def __init__(self):\n", + " self.x = 3" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = ALFA()\n", + "a.A" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.x" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.__class__.A" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ALFA.A" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## inheritance\n", + "A class can inherit from another class; in such case, it inherits all the contents, including methods. The methods can be redefined." + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "class BETA(ALFA):\n", + " def __init__(self):\n", + " ALFA.__init__(self) # call superclass constructor\n", + " self.y = 5" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b = BETA()\n", + "b.A" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 104, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.x" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.y" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## inheritance\n", + "super() function lets you delegate to a base classan operation:" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "class BETA(ALFA):\n", + " def __init__(self):\n", + " super().__init__() # => ALFA.__init__(self)\n", + " self.y = 5" + ] + } + ], + "metadata": { + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/03-Introduction_to_Python.ipynb b/03-Introduction_to_Python.ipynb new file mode 100644 index 0000000..e3d0e3d --- /dev/null +++ b/03-Introduction_to_Python.ipynb @@ -0,0 +1,2154 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## iterables \n", + "\n", + "We have seen various containers; all these are iterables, namely, it is possible to iterate through the elements of these objects (for example, with a loop).\n", + "\n", + "There are other objects on which it is possible to iterate, although strictly speaking not contain anything.\n", + "\n", + "We have seen some examples of iterables that have no content: `range, filter, map`..." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterables\n", + "We define a function similar to the range, but that creates and returns a list (unlike range, it starts from 1 and stop is included):" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def up_to(N):\n", + " \"\"\"Returns the list of integers 1...N\n", + " >>> up_to(3)\n", + " [1, 2, 3]\"\"\"\n", + " l = []\n", + " i = 1\n", + " while i < N + 1:\n", + " l.append(i)\n", + " i += 1\n", + " return l" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterables\n", + "Now consider the function sumn that sum the first N integers, using our function `up_to`:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def sumn(N):\n", + " \"\"\"Returns the sum of the first N integers. N is included.\"\"\"\n", + " s = 0\n", + " for i in up_to(N):\n", + " s += i\n", + " return s" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "55" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sumn(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "50005000" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sumn(10000)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterables\n", + "This is inefficient, because it creates a list of N elements, although it is always used one at a time. \n", + "\n", + "To add all the elements 1 to N is enough for me \"generate\" one after the other: there is no need to have them all at the same time in memory!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterables" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def up_to_iter(N):\n", + " \"\"\"Generates all the integers 1...N\n", + " >>> list(up_to_iter(3))\n", + " [1, 2, 3]\"\"\"\n", + " i = 1\n", + " while i < N + 1:\n", + " yield i\n", + " i += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterables\n", + "Let's use `up_to_iter()` function just created" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def sumn2(N):\n", + " \"\"\"sumn(N) -> sum of the integers 1...N\"\"\"\n", + " s = 0\n", + " for i in up_to_iter(N):\n", + " s += i\n", + " return s" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "55" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sumn2(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## generators and iterators\n", + "The function up_to_iter is a generator. It produces an iterable. The trick is to replace `return` with `yield`; both \"return\" to the caller expression at the right.\n", + "\n", + "The difference is that when yield is called, the function \"remains on the stack\", and its execution can be resumed from where it left off.\n", + "\n", + "The constructs for flow control (for, list comprehension, ...) do it automatically.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## generators ed iterators\n", + "\n", + "To be more accurate, the iteration involves two types of objects, usually separated:\n", + "\n", + "* __the iterable object__: is the sequence, the object that can be used for example directly in a for;\n", + "* __the iterator__ is the object that enables the iteration on a particular iterable object.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterable object\n", + "An iterable object is any object that implements the method `__iter__()`; when called, this method returns an iterator for the object." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterator\n", + "An iterator is any object that implements the method `__next__()`; when called, this method returns the next iteration element.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "lst = [1, 2, 3]\n", + "for i in lst:\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + }, + { + "ename": "StopIteration", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-9-521c4951927b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0miterator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0miter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlst\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# -> lst.__iter__()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mi\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# -> iterator.__next__()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mStopIteration\u001b[0m: " + ] + } + ], + "source": [ + "lst = [1, 2, 3]\n", + "iterator = iter(lst) # -> lst.__iter__()\n", + "while True:\n", + " i = next(iterator) # -> iterator.__next__()\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterators\n", + "If you know a bit of __object-oriented__ programming, it is not difficult to build an iterator in python; in general, it is an object that should simply keep some state between a call and the other of the method `__next__()` (must \"remember\" the last value product, and generate the next).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## why two classes and not one?\n", + "Why an iterable object delegate the iteration to a second object? Why it does not implement the method `__next__()` itself? After all, it has all the information to do so." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lst = [1, 2, 3]\n", + "hasattr(lst, '__iter__')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hasattr(lst, '__next__')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hasattr(iter(lst), '__next__')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## why two classes and not one?\n", + "The reason is that the iterator must maintain a state (must remember at what point is \n", + "the process of iteration):\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "Suppose we define a MyList class which implements directly **`__next__()`**\n", + "\n", + "```python\n", + "class MyList(object):\n", + " ...\n", + " def __iter__(self):\n", + " return self\n", + " def __next__(self):\n", + " value = self._values[self._index]\n", + " self._index += 1\n", + " return value\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "```python\n", + ">>> mylst = MyList([1, 2, 3])\n", + ">>> for i in mylst:\n", + "... print(i)\n", + "...\n", + "1\n", + "2\n", + "3\n", + ">>>\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "```python\n", + ">>> for i in mylst:\n", + "... print(i)\n", + "...\n", + ">>>\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## why two classes and not one?\n", + "Even Worse, it would not be possible the nested iteration:\n", + "\n", + "```python\n", + ">>> lst = [1, 2, 3]\n", + ">>> for i in lst:\n", + "... for j in lst:\n", + "... print(i, j)\n", + "...\n", + "1 1\n", + "1 2\n", + "1 3\n", + "2 1\n", + "2 2\n", + "2 3\n", + ">>>\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "```python\n", + ">>> mylst = MyList([1, 2, 3])\n", + ">>> for i in mylst:\n", + "... for j in mylst:\n", + "... print(i, j)\n", + "...\n", + "1 2\n", + "1 3\n", + ">>>\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## generators\n", + "A generator is therefore a \"trick\" to avoid manually construct two classes: one for the iterable object, \n", + "and one for the `iterator`.\n", + "\n", + "Defining a simple function that uses the `yield` instead of `return` and you get the purpose.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## infinite sequences\n", + "The benefit of iterators is that deliver even infinite sequences, with an insignificant memory allocation:\n", + "```python\n", + ">>> def even_numbers():\n", + "... i=2\n", + "... while True:\n", + "... yield i\n", + "... i += 2\n", + "... \n", + ">>> for n in even_numbers():\n", + "... if not is_sum_of_two_primes(n):\n", + "... print(\"Goldbach was wrong!\")\n", + "... break\n", + "...\n", + ">>>\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iteration" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [1, 2, 3]\n", + "il = iter(l)\n", + "next(il) # => l.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "next(il) # => l.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "next(il) # => l.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "StopIteration", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-20-6adbb62462de>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mil\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# => l.__next__()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m: " + ] + } + ], + "source": [ + "next(il) # => l.__next__()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## python2\n", + "In python2 many functions or methods return lists and not iterators. For example, the methods `keys`, `values`, `items` of the dictionaries return `lists`. \n", + "\n", + "However, there are the methods `iterkeys`, `itervalues`, `iteritems` that return `iterators`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## iterator\n", + "The concept of iterator is a typical example of design pattern, that is an efficient and diffused solution to a general problem.\n", + "\n", + "In python the concept is pervasive: everything that scrolls over an object from left to right does it through iterators.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## built-in functions that operate on iterators\n", + "There are many built-in functions that operate on iterables, for example container constructors:\n", + "* __list (iterable)__: builds a list\n", + "* __tuple (iterable)__: builds a tuple\n", + "* __dict (iterable)__: builds a dictionary (warning: the elements in `iterable` should be key/value pairs, that is tuples of two elements)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## built-in generators\n", + "\n", + "There are many useful built-in generators:\n", + "* `range([start,] stop[, incr])`: generates a sequence\n", + "* `zip(it1, it2)`: generates a sequence of pairs whoselements are taken from it1 and it2\n", + "* `enumerate(it)`: generates a sequence of pairs (i, e) where e is an element of it, and i its index.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## built-in generators\n", + "\n", + "<pre>\n", + ">>> l1 = ['a', 'b', 'c']\n", + ">>> l2 = [1, 2, 3]\n", + ">>> for a, b in zip(l1, l2):\n", + "... print(\"{}={}\".format(a, b))\n", + "...\n", + "a=1\n", + "b=2\n", + "c=3\n", + ">>> list(zip(l1, l2))\n", + "[('a', 1), ('b', 2), ('c', 3)]\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## built-in generators\n", + "<pre>\n", + ">>> l1 = ['a', 'b', 'c']\n", + ">>> l2 = [1, 2, 3]\n", + ">>> for k, v in zip(l1, l2):\n", + "... print(\"{}=={}\".format(k, v))\n", + "...\n", + "a==1\n", + "b==2\n", + "c==3\n", + ">>> dict(zip(l1, l2))\n", + "{'a': 1, 'c': 3, 'b': 2}\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## built-in generators\n", + "\n", + "<pre>\n", + ">>> l1 = ['a', 'b', 'c']\n", + ">>> for i, e in enumerate(l1):\n", + "... print(i, e)\n", + "...\n", + "0 a\n", + "1 b\n", + "2 c\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## generator expressions\n", + "If you use round brackets instead of square brackets, the same syntax \n", + "as the list comprehension allows you to define generators onÂtheÂfly:\n", + "\n", + "<pre>\n", + ">>> [i**3 for i in range(4)]\n", + "[0, 1, 8, 27]\n", + ">>> (i**3 for i in range(4))\n", + "<generator object <genexpr> at 0x7f30e99d3fa0>\n", + ">>> sum((i**3 for i in range(4)))\n", + "36\n", + ">>> sum(i**3 for i in range(4))\n", + "36\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## generator expressions\n", + "\n", + "<pre>\n", + ">>> g = range(1000000) \n", + ">>> sum([e**2 for e in g]) # list of 1000000 elements!\n", + "333332833333500000\n", + ">>> sum(e**2 for e in g) # generator\n", + "333332833333500000\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (primes.py)\n", + "* Write a generator \"primes\" that produces the sequence of prime numbers (all!). The efficiency is not important.\n", + "* Using the generator \"primes\", create a list of thefirst 250 prime numbers.\n", + "* Using the generator \"primes\", define a function \"`pi(N)`\" that returns the number of prime numbers less than `N`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## introspection\n", + "The introspection is the ability of a language to provide various information run-time about the objects.\n", + "\n", + "Python has an excellent support for introspection, unlike languages such as Fortran or C that have none, or C++, which has a very limited support.\n", + "\n", + "It is useful for:\n", + "* Debugging\n", + "* Learn more easily how to use libraries\n", + "* Develop certain algorithms\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## introspection\n", + "\n", + "Determine the type of an object is very easy: just use the `type` command:\n", + "\n", + "<pre>\n", + ">>> l = [1, \"alfa\", 0.9, (1, 2, 3)]\n", + ">>> print([type(i) for i in l])\n", + "[<class 'int'>, <class 'str'>, <class 'float'>, <class 'tuple'>]\n", + ">>>\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## introspection\n", + "Sometimes it is useful in functions, because the type of arguments of a function is not fixed, but it depends on how the function is called. \n", + "\n", + "The command `isinstance(obj, t)` tells us if the object obj is of type t:\n", + "\n", + "<pre>\n", + ">>> def dupl(a):\n", + "... if isinstance(a, list):\n", + "... return [dupl(i) for i in a]\n", + "... else:\n", + "... return 2*a\n", + "...\n", + ">>> dupl(10)\n", + "20\n", + ">>> dupl(['a', 3, [1, 2, 3]])\n", + "['aa', 6, [2, 4, 6]]\n", + ">>>\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## introspection\n", + "The function `dir()` returns a list containing the symbolic names of members of an object (attributes or \n", + "methods):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "l = [3, 4, 1]\n", + "print(type(l))\n", + "print(dir(l))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "print(l.sort.__doc__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "l.sort(key=lambda x: -x)\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## introspection\n", + "Often items have “special†attributes that contain useful information for introspection:\n", + "\n", + "<pre>\n", + ">>> print(l.__class__)\n", + "<class 'list'>\n", + ">>> print(l.__class__.__name__)\n", + "list\n", + ">>> f = l.sort\n", + ">>> print(f.__name__)\n", + "sort\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## introspection\n", + "Sometimes you want to know if an instance has a certain attribute:\n", + "\n", + "<pre>\n", + ">>> if hasattr(a, 'x'):\n", + "... print(a.x)\n", + "...\n", + "3\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## object structure\n", + "To understand how introspection works, it is useful to know how objects are structured." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "class ALFA(object):\n", + " A = 10\n", + " def __init__(self):\n", + " self.x = 3\n", + " \n", + "a = ALFA()\n", + "print(a.x, a.A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# class attributes\n", + "print(ALFA.__dict__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# instance attributes\n", + "print(a.__dict__)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## object structure\n", + "Each object has an attribute `__dict__` containing a dictionary; `__dict__` contains all the attributes of the object, indexed by its name:\n", + "\n", + "<pre>\n", + ">>> print(a.__dict__[\"x\"])\n", + "3\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## object structure\n", + "When you access an attribute of an object, first it searches in the dictionary of the object, then in the dictionary of his class (and possibly in the dictionary of the base classes):\n", + "\n", + "<pre>\n", + ">>> print(a.A)\n", + "10\n", + ">>> print(a.__dict__['A'])\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "KeyError: 'A'\n", + ">>> print(a.__class__.__dict__['A'])\n", + "10\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (interactive)\n", + "Using interpreter in interactive mode, determine how to use the following functions: `ord`, `chr`, `callable`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## modules\n", + "A file with extension .py is a python module. A module can contain any type of python code.\n", + "\n", + "The module can have its own doc string.\n", + "\n", + "The modules can also have extension .so, if they are produced from source C through python C-API.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "For example:\n", + "\n", + "<pre>\n", + "$ cat my.py\n", + "def hello_world():\n", + " print(“Hello, world!â€)\n", + "$ python3\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "source": [ + "<pre>\n", + ">>> import my\n", + ">>> dir(my)\n", + "['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'hello_world']\n", + ">>> print(my.__file__)\n", + "my.py\n", + ">>> my.hello_world()\n", + "Hello, world!\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "The module has an attribute `__name__` which coincides with the name of the module itself.\n", + "\n", + "But the module is basically a normal python source (the only element needed is the extension .py), so it can also be run as a program.\n", + "\n", + "In this case, the value of `__name__` is the string `\"__main__\"`" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "You can use this attribute to write modules that contain a \"main\" test; just add the code test, conditioned to the value of `__name__`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "<pre>\n", + "$ cat my.py \n", + "#!/usr/bin/env python3\n", + "\n", + "print(__name__)\n", + "\n", + "def hello_world():\n", + " print(\"Hello, world!\")\n", + " \n", + "if __name__ == \"__main__\":\n", + " hello_world()\n", + " hello_world()\n", + " hello_world()\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "<pre>\n", + "$ ./my.py \n", + "__main__\n", + "Hello, world!\n", + "Hello, world!\n", + "Hello, world!\n", + "\n", + "$ python3\n", + "Python 3.2.3 (default, Oct 19 2012, 20:10:41) \n", + "[GCC 4.6.3] on linux2\n", + "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n", + ">>> import my\n", + "my \n", + ">>> \n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "A module can be imported in several ways:\n", + "\n", + "<pre>\n", + ">>> import mymodule\n", + ">>> mymodule.myf1()\n", + ">>> from mymodule import myf1, myf2\n", + ">>> myf1()\n", + ">>> from mymodule import myf1 as yourf1\n", + ">>> yourf1()\n", + ">>> from mymodule import *\n", + ">>> myf10()\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## modules\n", + "Importing from a module with `'*'`, by default it imports all the symbols of the module whose name does not begin with an underscore.\n", + "\n", + "If the module contains a variable `__all__`, this must be a list of the names of the symbols imported when importing with `'*'`.\n", + "<pre>\n", + "$ cat my.py\n", + "__all__ = [ 'hi_folk']\n", + "...\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## packages\n", + "The modules can be grouped into packages, which have a hierarchical structure represented by directories. A directory that contains an `__init__.py` file, possibly empty, is a valid python package. If the directory contains other packages or modules, they are available as package content.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## packages\n", + "<pre style=\"font-size:50%;\">\n", + "sound/ Top-level package\n", + " __init__.py Initialize the sound package\n", + " formats/ Subpackage for file format conversions\n", + " __init__.py \n", + " aiffread.py \n", + " aiffwrite.py \n", + " auread.py\n", + " auwrite.py \n", + " ...\n", + " effects/ Subpackage for sound effects\n", + " __init__.py \n", + " echo.py \n", + " surround.py\n", + " reverse.py \n", + " ...\n", + " filters/ Subpackage for filters\n", + " __init__.py \n", + " equalizer.py \n", + " vocoder.py\n", + " karaoke.py \n", + " ...\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## packages\n", + "\n", + "<pre>\n", + ">>> import sound.effects.echo.echofilter\n", + ">>> sound.effects.echo.echofilter(...)\n", + ">>> import sound.effects.echo\n", + ">>> sound.effects.echo.echofilter(...)\n", + ">>> from sound.effects import echo\n", + ">>> echo.echofilter(...)\n", + ">>> from sound.effects.echo import echofilter\n", + ">>> echofilter(...)\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## packages\n", + "\n", + "As for the modules, you can import with `'*'` from a package, but only if `__init__.py` defines `__all__=[...]`; In fact, the determination of the module name from the files contained in the directory of the package is not possible in Windows (case insensitive file names).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (interactive mode)\n", + "\n", + "* In interactive mode import the module \"primes\", discover the content and try to use the functions of the module.\n", + "* Try to import the module \"math\" and to discover its content.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## pydoc\n", + "Pydoc is a tool, obviously written in python, which uses introspection to provide the information stored in a module in a clear and compact solution.\n", + "\n", + "Pydoc uses the doc strings `__doc__` and many other standard attributes of the objects (`__name__`, `__file__`, ...).\n", + "\n", + "Since we are using python3, probably you have to use pydoc3.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## pydoc\n", + "\n", + "<pre style=\"font-size:70%;\">\n", + "$ pydoc3 math\n", + "Help on built-in module math:\n", + "\n", + "NAME\n", + " math\n", + "\n", + "DESCRIPTION\n", + " This module is always available. It provides access to the\n", + " mathematical functions defined by the C standard.\n", + "\n", + "FUNCTIONS\n", + " acos(...)\n", + " acos(x)\n", + " \n", + " Return the arc cosine (measured in radians) of x. \n", + "\n", + "...\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## help()\n", + "In interactive mode, the `help` function does the same thing pydoc does.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (interactive mode)\n", + "* Use pydoc or help() to find out the content of primes\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## program arguments\n", + "To access the arguments with the program was called which, you have to import the sys module and access the variable `sys.argv`. This is a list of strings; `sys.argv[0]` is the name of the program, the remaining elements are the arguments passed to the command line.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## program arguments\n", + "\n", + "<pre>\n", + "#!/usr/bin/env python3\n", + "import sys\n", + "for arg in sys.argv:\n", + " print(arg)\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## program arguments\n", + "It is not convenient to do a manual parsing of the arguments: it is better to use the library `argparse`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## file I/O\n", + "Let's see how you write a text file:\n", + "\n", + "<pre>\n", + ">>> with open(\"a.txt\", \"w\") as f:\n", + "... f.write(\"Hello, \")\n", + "... f.write(\"world!\\n\") \n", + "7 # These are simply the return values of the two write \n", + "7 # (the number of characters written) \n", + ">>>\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## file I/O\n", + "You can read line by line by iterating on file; warning, the newline `'\\n'` is part of the string read!\n", + "\n", + "<pre>\n", + ">>> with open(\"a.txt\", \"r\") as f:\n", + "... for line in f:\n", + "... print(line)\n", + "Hello, world!\n", + "\n", + ">>>\n", + "</pre>\n", + "\n", + "Read lines contain the newline, to remove it you can use `str.strip()`" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## file I/O\n", + "\n", + "You can read a single line at a time with readline():\n", + "\n", + "<pre>\n", + ">>> with open(\"a.txt\", \"r\") as f:\n", + " print(f.readline()) \n", + "Hello, world!\n", + "\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## file I/O\n", + "Or you can read all lines through readlines():\n", + "\n", + "<pre>\n", + ">>> with open(\"a.txt\", \"r\") as f:\n", + "... print(f.readlines())\n", + "...\n", + "['Hello, world!\\n']\n", + ">>> \n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## closing the file\n", + "\n", + "If you use the construct `with` (context manager), you not have to worry about closing the file: it will be automatically closed with block exit. \n", + "\n", + "Do not use any other way to open files!\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (files.py)\n", + "\n", + "* Read the list of arguments from the command line, and print (one argument per line) all arguments on a file whose name matches the name of the python program plus the extension '.out' (`files.py.out`, but it must also work renaming the program!).\n", + "\n", + "* Reread all the arguments from the file and print them.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## error handling\n", + "Error handling is a complex problem, which the modern languages face off in a completely different way than the \"old\" ones. \n", + "\n", + "First, we must be aware of the fact that the place where an error is detected (for example, a library function such as `sqrt`) is not the same place where the error can be \"treated\" (for example, the main program).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "The requirements of a modern system for handling errors are:\n", + "* Low or no impact on performance, when no error are generated\n", + "* Little invasiveness on code\n", + "* You should not have to \"pass\" the error by hand\n", + "* It must be possible to manage the error \"partially\" (sometimes you can not completely solve the error at one point, but you can apply only a part of the correction)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "Suppose you have a stack of function calls like this:\n", + "<pre style='font-size:50%;'>\n", + "main\n", + " |__compute_matrix <- here the error ZeroDivisionError can be handled completely\n", + " |__compute_cell <- here the errot BadStartingPoint can be handled, and the error \n", + " | ZeroDivisionError can be handled partially\n", + " |__compute_radix_of_function \n", + " |__ newton -> here the error BadStartingPoint can be detected\n", + " |__function_C -> here the error ZeroDivisionError can be detected\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "In Fortran, for example, it is used a variable returned by the function/subroutine to pass any error.\n", + "\n", + "In this case, the variable containing the error should be passed manually backwards, for example from `function_C`, to `newton`, to `compute_radix_of_function`, to `compute_cell`, to `compute_matrix`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "What are the drawbacks?\n", + "\n", + "* It is a tedious and boring activity that normally lead to errors\n", + "* It makes the code much longer and more complicated\n", + "* Adds overhead even without error (there will be some __if__ checking the state variables of the function that generates the error, for example).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "All modern systems use a different approach. \n", + "\n", + "Consider the error BadStartingPoint.\n", + "\n", + "At the point where the error can be identified (newton), an exception of type `BadStartingPoint` is launched. For now, do not worry about what `BadStartingPoint` is: it could be anything, an `int`, a `string`, a `list` etc...\n", + "\n", + "In python, exceptions are launched with the `raise` command. In `fun_B` it will appear something like:\n", + "```python\n", + "if ...:\n", + " raise BadStartingPoint()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "When an exception is launched, the program flow is interrupted, and the stack is automatically \"rolled backâ€, back to the function that called the one who launched the exception, and back again if necessary, up to a point where the error can be \"treated\". The computation resumes from this point.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "How do you determine who can treat a certain error?\n", + "\n", + "It's simple: the code block that could handle a `BadStartingPoint` exception is enclosed in a special section; when that exception occurs, it will be executed the associated handling section. The syntax is based on the python `try/except` statement.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "Therefore, in the function where we determined that the error can be treated (compute_cell) it is inserted a `try/except` block:\n", + "\n", + "<pre>\n", + "def compute_cell(matrix, i, j):\n", + " # ...\n", + " try:\n", + " matrix[i][j] += compute_radix_of_function(f, cell, x_0)\n", + " except BadStartingPoint as e:\n", + " print(\"ERR: {0}: {0}\".format(e.__class__.__name__, e))\n", + " X_0 += 0.4\n", + " # ...\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "In the intermediate functions nothing changes: they are not involved from the exception.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "In the case of `ZeroDivisionError`, however, the handling is more complex: `compute_cell` can partially repair the error, but not completely. \n", + "\n", + "The rest of the work is done by `compute_matrix`.\n", + "\n", + "In this case, the exception is collected, partially managed and relaunched, with the `raise` command:\n", + "\n", + "<pre>\n", + "# ...\n", + "except ZeroDivisionError as e:\n", + " print(\"ERR: ZeroDivisionError: resetting cell\")\n", + " matrix[i][j] = 0.0\n", + " raise\n", + "# ...\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "At this point the stack is again rolled back to `compute_matrix`, which completes the error handling.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "Generally, exceptions are defined hierarchically. In our example, there are three types of BadStartingPoint errors:\n", + "\n", + "* `StationaryStartingPoint`\n", + "* `CyclingStartingPoint`\n", + "* `SlowlyConvergingStartingPoint`\n", + "\n", + "`newton` launches all these three errors." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "These three types of error are handled the same way by compute_cell, but it is possible that other functions that call `newton` must treat them differently.\n", + "\n", + "This is accomplished by creating a class `BadStartingPoint`, and the three classes `StationaryStartingPoint`, `CyclingStartingPoint`, `SlowlyConvergingStartingPoint` that inherit from `BadStartingPoint`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## error handling\n", + "\n", + "What `BadStartingPoint`, `StationaryStartingPoint`, ... are? They are \"types\" of exceptions, or, more generally, \"types\": like `int`, `str`, ...\n", + "\n", + "However, they are user-defined types, or `classes`.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## try/except\n", + "\n", + "<pre style=\"font-size:70%;\">\n", + "try:\n", + " ...\n", + " ...\n", + "except Exc0:\n", + " ... # catches exceptions type Exc0\n", + "except Exc1 as excInstance:\n", + " ... # catches exceptions type Exc1, \n", + " # and its instance is excInstance\n", + "except (Exc2, Exc3):\n", + " ... # catches exceptions type Exc2 o Exc3\n", + "except (Exc4, Exc5) as excInstance:\n", + " ... # catches exceptions type Exc2 o Exc3, \n", + " # and their instance is excInstance\n", + "except:\n", + " ... # catches any exception\n", + "else:\n", + " ... # executed only if no exceptions were captured\n", + "finally:\n", + " ... # executed always and anyway\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## else/finally example\n", + "\n", + "<pre>\n", + "try:\n", + " f = open(\"a.txt\", \"r\") # NEVER DO THIS! USE: with open(...)\n", + " do_some_action_on_file(f)\n", + "except:\n", + " print(\"ERROR\")\n", + "else:\n", + " print(\"OK\")\n", + "finally:\n", + " f.close()\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## standard exceptions\n", + "Now we can better understand what happens when there is an error in a program:\n", + "\n", + "<pre>\n", + ">>> a = 4/0\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "ZeroDivisionError: integer division or modulo by zero\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## standard exceptions\n", + "\n", + "<pre>\n", + ">>> l = [1, 2, 3]\n", + "\n", + ">>> print(l[10])\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "IndexError: list index out of range\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## standard exceptions\n", + "\n", + "<pre>\n", + ">>> l.remove(444)\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "ValueError: list.remove(x): x not in list\n", + "\n", + ">>> d = {}\n", + ">>> print(d['alfa'])\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "KeyError: 'alfa'\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## standard exceptions\n", + "\n", + "<pre>\n", + ">>> l = [1, 2]\n", + ">>> il = iter(l)\n", + ">>> next(il)\n", + "1\n", + ">>> next(il)\n", + "2\n", + ">>> next(il)\n", + "Traceback (most recent call last):\n", + " File \"<stdin>\", line 1, in <module>\n", + "StopIteration\n", + ">>>\n", + "</pre>\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## standard exceptions\n", + "We now know that a for loop ends when the iterator on which it operates launches an exception StopIterator!\n", + "\n", + "<pre>\n", + ">>> def rangeIter(n):\n", + "... i = 0\n", + "... while True:\n", + "... if i >= n: raise StopIteration\n", + "... yield i\n", + "... i += 1\n", + "...\n", + ">>> for i in rangeIter(3):\n", + "... print(i)\n", + "...\n", + "0\n", + "1\n", + "2\n", + ">>>\n", + "</pre>" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## test (primes.py)\n", + "* Change the function `is_prime` to generate an error if the argument is not an integer, or if it is a negative integer.\n", + "* Write a test program with error handling.\n" + ] + } + ], + "metadata": { + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} -- GitLab