Introduction to python

Python is a programming language created by Guido Van Rossum in 1989, to "correct the problems of other programming languages".

Characteristics of python:

  • interpreted language, therefore interactive;
    However, it is possible (even suggested!) to create libraries containing functions and scripts to execute complicated tasks as function of parameters. For these reasons, it is widely used as a tool for data analysis.
    Example:
In [1]:
10*13
Out[1]:
130
In [5]:
a=1.25
b=3.14
a*b
Out[5]:
3.9250000000000003
  • It is an object oriented language. However, it allows both procedural and object oriented programming, so that one can choose the preferred (or more effective) paradigm.
  • There is an enormous quantity of libraries available for doing practically everything.
    Example:
  • In [6]:
    import urllib.request
    
    file = urllib.request.urlopen("http://www.fis.unical.it/astroplasmi/primavera/comp_phys/comp_phys.html")
    data = file.read()
    print( data )
    
    b'<html>\n\n<head>\n  <!doctype html>\n  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\n  <meta http-equiv="Pragma" content="no-cache">\n  <title>Computational Physics</title>\n</head>\n\n<body>\n  <h1>Course on computational physics</h1>\n  <h2>Slides and programs of the course</h2>\n  <ul>\n\n    <li/><b>Systems of linear equations:</b>\n    <br/> Programs to solve systems of linear equations: <a href="Linear_systems.pdf">Lectures</a>, <a href="Linear_systems.tar.gz">Programs</a>.<br/>\n    The .tar.gz archive contains the following programs:\n      <ol>\n        <li/>Program System.cpp: solves a 3x3 system of linear equations through the algorithm of LU factorization;\n        <li/>Program Sys_scal.cpp: solves a system of linear equations with dimension NxN to analyze the computational complexity of the LU factorization;\n        <li/>Program Sys_ndd.cpp: solves a system of linear equations with dimension NxN but which is <b>NOT</b> diagonally dominant to see how the truncation errors propagate during the computation;\n\t<li/>Program Inverse.cpp: computes the inverse matrix of a 3x3 matrix by solving 3 different systems through the LU factorization;\n\t<li/>Program Tridiag.cpp: solves a tridiagonal linear system for a 3x3 matrix through the Thomas\' algorithm;\n\t<li/>Files LUvect.h and LUvect.cpp: class to deal with vectors, used by LUmat and LUtrid;\n\t<li/>Files LUmat.h and LUmat.cpp: class to solve NxN generic systems;\n\t<li/>Files LUtrid.h and LUtrid.cpp: class to solve generic tridiagonal systems;\n\t<li/>File makefile: makefile for all programs in the directory.\n      </ol>&nbsp;\n\n    <li/><b>Zeros of functions:</b>\n    <br/> Programs to compute the roots of transcendental functions: <a href="Zeros_of_functions.pdf">Lectures</a>, <a href="Zeros_of_functions.tar.gz">Programs</a>.<br/>\n    The .tar.gz archive contains the following programs:\n      <ol>\n        <li/>Program Bisection_example.cpp: finds the root of the equation: exp(x)-3/2=0 by using the bisection method;\n        <li/>Program Newton_example.cpp: finds the root of the equation: exp(x)-3/2=0 and of another (more complicated!) function by using the Newton\'s method;\n\t<li/>File Bisection.h: contains the function \'bisection\', which computes the interval containing the root through the bisection method;\n\t<li/>File Newton.h: contains the function \'newton\', which computes the interval containing the root through the Newton\'s method;\n\t<li/>File makefile: makefile for all programs in the directory.\n      </ol>&nbsp;\n\n    <li/><b>Integrals:</b>\n    <br/> Programs to compute definite integrals of functions: <a href="Integrals.pdf">Lectures</a>, <a href="Integrals.tar.gz">Programs</a>.<br/>\n    The .tar.gz archive contains the following programs:\n      <ol>\n        <li/>Program Trapezoidal.cpp: program to compute the integral of the function exp(x) between [0,2] with the trapezoidal rule;\n        <li/>Program Simpson.cpp: program to compute the integral of the function exp(x) between [0,2] with Simpson\'s rule;\n        <li/>File Integrals.cpp: library of functions for computing integrals with the trapezoidal and Simpson\'s rule;\n\t<li/>File Integrals.h: contains the headers for the functions defined in \'Integrals.cpp\';\n\t<li/>File Makefile: makefile for all programs in the directory.\n      </ol>&nbsp;\n\n  </ul>\n\n  <hr>\n\n  <a href="../didattica.html">Returns to the previous page</a>\n\n</body>\n\n</html>\n'
    
    
  • Extremely clear syntax: the programs are very easy to read, thanks to indentation (see below!). Moreover, there exist a set of commands (help(), type(), dir()) which supply immediate information to remember the commands and the functions.
    Example:
  • In [11]:
    import math
    print( math.pi )
    type(math.pi)
    #dir( math )
    #help( math.pi)
    
    3.141592653589793
    
    
    Out[11]:
    float
    
  • Written in C and extensible in C and C++
  • Portable on nearly every platform (Windows, Linux, Mac OS X, Unix BSD, Playstation, Digital VMS, Pocket PC, Windows CE, Amiga 500, etc.). To download: http://www.python.org
  • Data types

    Ordinary programming languages generally use variables to store data of various kind: numbers, characters, strings, and so on...
    In python, basic variables can be of type: integer, real, character, string.
    In ordinary compiled languages the type of the variable MUST be declared BEFORE using the variable and it cannot be changed afterwards! In python (as it is common in interpreted languages) a variable does not need to be declared, the initialization is enough to define the type and it can be re-initialized everywhere by changing its type!
    Example:

    In [13]:
    a=100
    type(a)
    
    Out[13]:
    int
    
    In [14]:
    a=1.2
    type(a)
    
    Out[14]:
    float
    
    In [17]:
    b=18.25
    type(b)
    
    Out[17]:
    float
    
    In [18]:
    s="Ciao!"
    type(s)
    
    Out[18]:
    str
    

    Characteristic of data types in python

    Differences between data in python and other languages:
    • integers have infinite precision!
      Example:
    In [15]:
    # This is 2 to 10000!
    2**10000
    
    Out[15]:
    19950631168807583848837421626835850838234968318861924548520089498529438830221946631919961684036194597899331129423209124271556491349413781117593785932096323957855730046793794526765246551266059895520550086918193311542508608460618104685509074866089624888090489894838009253941633257850621568309473902556912388065225096643874441046759871626985453222868538161694315775629640762836880760732228535091641476183956381458969463899410840960536267821064621427333394036525565649530603142680234969400335934316651459297773279665775606172582031407994198179607378245683762280037302885487251900834464581454650557929601414833921615734588139257095379769119277800826957735674444123062018757836325502728323789270710373802866393031428133241401624195671690574061419654342324638801248856147305207431992259611796250130992860241708340807605932320161268492288496255841312844061536738951487114256315111089745514203313820202931640957596464756010405845841566072044962867016515061920631004186422275908670900574606417856951911456055068251250406007519842261898059237118054444788072906395242548339221982707404473162376760846613033778706039803413197133493654622700563169937455508241780972810983291314403571877524768509857276937926433221599399876886660808368837838027643282775172273657572744784112294389733810861607423253291974813120197604178281965697475898164531258434135959862784130128185406283476649088690521047580882615823961985770122407044330583075869039319604603404973156583208672105913300903752823415539745394397715257455290510212310947321610753474825740775273986348298498340756937955646638621874569499279016572103701364433135817214311791398222983845847334440270964182851005072927748364550578634501100852987812389473928699540834346158807043959118985815145779177143619698728131459483783202081474982171858011389071228250905826817436220577475921417653715687725614904582904992461028630081535583308130101987675856234343538955409175623400844887526162643568648833519463720377293240094456246923254350400678027273837755376406726898636241037491410966718557050759098100246789880178271925953381282421954028302759408448955014676668389697996886241636313376393903373455801407636741877711055384225739499110186468219696581651485130494222369947714763069155468217682876200362777257723781365331611196811280792669481887201298643660768551639860534602297871557517947385246369446923087894265948217008051120322365496288169035739121368338393591756418733850510970271613915439590991598154654417336311656936031122249937969999226781732358023111862644575299135758175008199839236284615249881088960232244362173771618086357015468484058622329792853875623486556440536962622018963571028812361567512543338303270029097668650568557157505516727518899194129711337690149916181315171544007728650573189557450920330185304847113818315407324053319038462084036421763703911550639789000742853672196280903477974533320468368795868580237952218629120080742819551317948157624448298518461509704888027274721574688131594750409732115080498190455803416826949787141316063210686391511681774304792596709376
    
  • floating point numbers are always double precision!
    Example:
  • In [17]:
    # Square root of 10 (quite close to pi!)
    10.0**0.5
    
    Out[17]:
    3.1622776601683795
    
  • It exists a complex data type for complex numbers!
    The imaginary unit is indicated with j.
    Example:
  • In [18]:
    # Square root of 1+2I
    a=1.0+2.0j
    a**0.5
    
    Out[18]:
    (1.272019649514069+0.7861513777574233j)
    
  • The Boolean type is indicated through the values "True" or "False" (Note the capitalized initials!)
    Example:
  • In [19]:
    # Here a is re-defined with a boolean value
    x=10
    a=x>5
    a
    
    Out[19]:
    True
    

    Type convertions

    The following functions perform some type convertion:
    • str(number): converts a number in a string;
    • int(string) or int(real): from string or double to integer;
    • float(string) or float(int): from string or integer to double.

    Examples:

    In [42]:
    a=12.2
    s=str(a)
    s
    
    Out[42]:
    '12.2'
    
    In [44]:
    s="3.1415926"
    float(s)
    
    Out[44]:
    3.1415926
    
    In [45]:
    s=12345
    int(s)
    
    Out[45]:
    12345
    

    Lists

    All computer languages define the so-called vectors or arrays.
    In python, the same function is accomplished through the lists, that, however, at difference with vectors in other languages, may even contain eterogeneous elements, namely of different types.
    Examples:

    In [20]:
    mylist=[1.2,3.45,7.36,8.55]
    mylist
    
    Out[20]:
    [1.2, 3.45, 7.36, 8.55]
    
    In [22]:
    mylist=[1,2,3,"Hello world!"]
    mylist
    
    Out[22]:
    [1, 2, 3, 'Hello world!']
    

    The single elements of the list can be indexed through their position inside the list with an index ranging from 0 to the number of elements minus one. The index has to be surrounded by square brackets:

    In [23]:
    mylist=[1,3,5,7,9]
    mylist[3]
    
    Out[23]:
    7
    

    Any element in a list can be modified:

    In [24]:
    mylist[2]=101
    mylist
    
    Out[24]:
    [1, 3, 101, 7, 9]
    

    One may apply the so-called "slicing" to a list, through which several elements can be extracted at the same time (notice that the slicing returns all the elements from the first index to the second minus one!):

    In [25]:
    mylist[0:3]
    
    Out[25]:
    [1, 3, 101]
    

    A negative index indicates an element, starting from the last one:

    In [26]:
    mylist[0:-2]
    
    Out[26]:
    [1, 3, 101]
    

    If you do not indicate the first or second element, python assumes the element 0 or the last one, respectively:
    Example (prints the last two elements):

    In [27]:
    mylist[-2:]
    
    Out[27]:
    [7, 9]
    
    In [28]:
    mylist[:2]
    
    Out[28]:
    [1, 3]
    

    To eliminate a series of elements from a list, you can assign them to the empty list:

    In [29]:
    mylist[2:4]=[]
    mylist
    
    Out[29]:
    [1, 3, 9]
    

    The slicing may contain a third index, meaning that the elements must be returned from the first to the second index minus one, with a step given by the third index.
    Example:

    In [30]:
    mylist=[1,2,3,4,5,6,7,8,9,10]
    mylist[2:10:2]
    
    Out[30]:
    [3, 5, 7, 9]
    

    Methods for the lists

    • append(elem):
      appends an element to the list
    • insert(int,elem):
      inserts "elem" into the position "int" (starts from 0!). Note: to insert at the end of a list (namely to append) one can select an index greater or equal to the last element of the list!
    • extend([list]):
      extends the list with another list, returning a longer list
    • remove(elem):
      removes an element from the list (opposite of insert!)
    • pop() or pop(int):
      extracts and prints the last element from the list, if the argument is absent, or the element identified by the number "int" if it is present
    • count(elem):
      counts the elements equal to "elem" in the list
    • index(elem):
      gives the first occurrence of "elem" in the list (warning! it gives an error if the element does not exists!)
    • reverse():
      reverses a list, by overwriting it!
    • sort():
      sorts the list with different criteria and overwrites it

    Examples:

    In [31]:
    mylist=[1,2,3,4,5]
    mylist
    
    Out[31]:
    [1, 2, 3, 4, 5]
    
    In [32]:
    mylist.append(10)
    mylist
    
    Out[32]:
    [1, 2, 3, 4, 5, 10]
    
    In [33]:
    mylist.insert(1,11)
    mylist
    
    Out[33]:
    [1, 11, 2, 3, 4, 5, 10]
    
    In [34]:
    mylist.extend([20,30,40,50])
    mylist
    
    Out[34]:
    [1, 11, 2, 3, 4, 5, 10, 20, 30, 40, 50]
    
    In [35]:
    mylist.remove(20)
    mylist
    
    Out[35]:
    [1, 11, 2, 3, 4, 5, 10, 30, 40, 50]
    
    In [36]:
    mylist.pop()
    
    Out[36]:
    50
    
    In [37]:
    mylist
    
    Out[37]:
    [1, 11, 2, 3, 4, 5, 10, 30, 40]
    
    In [38]:
    mylist.append(1)
    mylist.count(1)
    
    Out[38]:
    2
    
    In [39]:
    mylist
    
    Out[39]:
    [1, 11, 2, 3, 4, 5, 10, 30, 40, 1]
    
    In [40]:
    mylist.index(1)
    
    Out[40]:
    0
    
    In [41]:
    mylist.pop(0)
    
    Out[41]:
    1
    
    In [42]:
    mylist.index(1)
    
    Out[42]:
    8
    
    In [43]:
    mylist.reverse()
    mylist
    
    Out[43]:
    [1, 40, 30, 10, 5, 4, 3, 2, 11]
    
    In [44]:
    mylist.sort()
    mylist
    
    Out[44]:
    [1, 2, 3, 4, 5, 10, 11, 30, 40]
    
    In [45]:
    # Sorts in reverse order!
    mylist.sort(reverse=True)
    mylist
    
    Out[45]:
    [40, 30, 11, 10, 5, 4, 3, 2, 1]
    

    Operator "in"

    The operator "in" returns True or False according to the fact that the left term exists or not in the list
    Example:

    In [25]:
    ll=[1,3,5,7,9,11]
    3 in ll
    
    Out[25]:
    True
    
    In [26]:
    4 in ll
    
    Out[26]:
    False
    

    Function len

    The function len(list) returns the lenght of the list (number of elements). Warning! it is a function, NOT a method!
    Example:

    In [2]:
    ll=[10,20,30,40,50]
    print(len(ll))
    
    5
    
    

    Lists of lists (arrays)

    In python one may create variables with 2 or more indices (like arrays in other languages!) by using lists of lists.
    Example:

    In [13]:
    arr=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
    arr
    
    Out[13]:
    [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
    
    In [14]:
    arr[1]
    
    Out[14]:
    [4, 5, 6]
    
    In [15]:
    arr[1][2]
    
    Out[15]:
    6
    

    Strings

    Strings in python may be delimited with either single or double quotes.
    Strings can be merged by using the operator "+":

    In [46]:
    s1="Hello"
    s2="world!"
    s1 + ' ' + s2
    
    Out[46]:
    'Hello world!'
    

    Strings may be repeated by using the operator "*":

    In [47]:
    s1="Python is "
    s2="beautiful, "
    s1 + s2 * 10 + "beautiful!"
    
    Out[47]:
    'Python is beautiful, beautiful, beautiful, beautiful, beautiful, beautiful, beautiful, beautiful, beautiful, beautiful, beautiful!'
    

    Strings may contain escape sequences like in C.

    In [48]:
    s1="Remember to send an email to:\n"
    s2="\t"
    s3="leonardo.primavera\x40unical.it"
    print(s1 + s2 + s3)
    
    Remember to send an email to:
    	leonardo.primavera@unical.it
    
    

    Strings may extend on several lines by inserting them between triple single or double quotes:

    In [49]:
    s="""
    This is an example of a very long string...
    reallt long...
    """
    print(s)
    
    
    This is an example of a very long string...
    reallt long...
    
    
    

    The strings are similar to lists, and the slicing is supported:

    In [20]:
    s="abcdefghilmnopqrstuvz"
    s[1:-1]
    
    Out[20]:
    'bcdefghilmnopqrstuv'
    
    In [21]:
    s[::4]
    
    Out[21]:
    'aeiosz'
    

    However, notice that, at difference with lists, the strings are immutable and cannot be changed!
    Example:

    In [50]:
    s="aeiou"
    s[2]="c"
    
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-50-7992904794b8> in <module>()
          1 s="aeiou"
    ----> 2 s[2]="c"
    
    TypeError: 'str' object does not support item assignment
    There are special methods for the strings:
    • find(str): finds "str" inside the object string.
    • strip(): returns a string equal to the object string with removed initial and final spaces.
    • replace(str1,str2): returns a string equal to the object string with "str1" replaced by "str2".
    • split(str): splits the string according to the "str" argument. Note that it returns a list!
    • str.join(lista): joins the elements of the argument "list" with the string "str".

    Examples:

    In [51]:
    s='  abcde  '
    s.find("c")
    
    Out[51]:
    4
    
    In [52]:
    s.strip()
    
    Out[52]:
    'abcde'
    
    In [53]:
    s.replace(" ","<<")
    
    Out[53]:
    '<<<<abcde<<<<'
    
    In [54]:
    s="This string contains some commas, to improve the readibility, however, sometimes, it's better to separate the sentences"
    s.split(",")
    
    Out[54]:
    ['This string contains some commas',
     ' to improve the readibility',
     ' however',
     ' sometimes',
     " it's better to separate the sentences"]
    
    In [55]:
    '/'.join(["12","10","1492"])
    
    Out[55]:
    '12/10/1492'
    

    Further methods for the strings (as well as for other entities!) may be obtained through the commands: dir(s) or help(s):

    In [56]:
    dir(s)
    
    Out[56]:
    ['__add__',
     '__class__',
     '__contains__',
     '__delattr__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__getitem__',
     '__getnewargs__',
     '__gt__',
     '__hash__',
     '__init__',
     '__iter__',
     '__le__',
     '__len__',
     '__lt__',
     '__mod__',
     '__mul__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__rmod__',
     '__rmul__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     'capitalize',
     'casefold',
     'center',
     'count',
     'encode',
     'endswith',
     'expandtabs',
     'find',
     'format',
     'format_map',
     'index',
     'isalnum',
     'isalpha',
     'isdecimal',
     'isdigit',
     'isidentifier',
     'islower',
     'isnumeric',
     'isprintable',
     'isspace',
     'istitle',
     'isupper',
     'join',
     'ljust',
     'lower',
     'lstrip',
     'maketrans',
     'partition',
     'replace',
     'rfind',
     'rindex',
     'rjust',
     'rpartition',
     'rsplit',
     'rstrip',
     'split',
     'splitlines',
     'startswith',
     'strip',
     'swapcase',
     'title',
     'translate',
     'upper',
     'zfill']
    

    Tuples

    Tuple are similar to lists, but they are immutable, like the strings, therefore they cannot be modified!
    However, we need them since they are pretty much used, for instance to shape arrays in numpy.
    To define a tuple, we use ().
    Example:

    In [57]:
    a=(1,2,3,4,'mha!')
    a[1:-1]
    
    Out[57]:
    (2, 3, 4)
    
    In [58]:
    a[1]
    
    Out[58]:
    2
    
    In [59]:
    a[1]=18
    
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-59-1b7326119766> in <module>()
    ----> 1 a[1]=18
    
    TypeError: 'tuple' object does not support item assignment

    Sets

    Sets are a data type which is similar to sets in mathematics. Through sets, you can manage ensembles of data with no particular order and without duplicates.
    To create a set one has to use the set keyword.
    Example:

    In [78]:
    myset = set(["one", "two", "three"])
    myset
    
    Out[78]:
    {'one', 'three', 'two'}
    

    The initializer of the set can be any sequence of values, like a list in the example above, but also a tuple or a string.
    Example:

    In [80]:
    myset = set( "Hello World!" )
    myset
    
    Out[80]:
    {' ', '!', 'H', 'W', 'd', 'e', 'l', 'o', 'r'}
    
    On the sets, one can carry out the normal operation on sets in mathematics, like:
    • Union: symbol "|", all the elements belonging to either the first or the second set;
    • Difference: symbol "-", all the elements of the first set which do not belong to the second one;
    • Intersection: symbol "&", all the elements which belong to both the two sets;
    • xor: symbol "^", all the elements belonging either to the first or to the second set, but not to both.

    Examples:

    In [81]:
    myset1=set( "albert einstein" )
    myset2=set( "isaac newton" )
    myset1, myset2
    
    Out[81]:
    ({' ', 'a', 'b', 'e', 'i', 'l', 'n', 'r', 's', 't'},
     {' ', 'a', 'c', 'e', 'i', 'n', 'o', 's', 't', 'w'})
    
    In [82]:
    myset1 | myset2
    
    Out[82]:
    {' ', 'a', 'b', 'c', 'e', 'i', 'l', 'n', 'o', 'r', 's', 't', 'w'}
    
    In [83]:
    myset1 - myset2
    
    Out[83]:
    {'b', 'l', 'r'}
    
    In [84]:
    myset1 & myset2
    
    Out[84]:
    {' ', 'a', 'e', 'i', 'n', 's', 't'}
    
    In [85]:
    myset1 ^ myset2
    
    Out[85]:
    {'b', 'c', 'l', 'o', 'r', 'w'}
    

    Dictionaries

    A dictionary in python is an associative array, namely it works like a list, but the values are indexed through a key, instead of a number!
    To create a dictionary one has to initialize it with the construct "dict()", then add to it the key-value couples.
    Example:

    In [67]:
    diet=dict()
    diet["Pasta"]=125
    diet["Meat"]=300
    diet["Fruit"]=150
    diet
    
    Out[67]:
    {'Meat': 300, 'Pasta': 125, 'Fruit': 150}
    

    Another way to initialize a dictionary is to put the keys-values couples in brackets {}, separated by a semicolon (:).
    Example:

    In [61]:
    dd={"Meat": 300, "Fruit": 150, "Pasta": 125}
    dd
    
    Out[61]:
    {'Meat': 300, 'Fruit': 150, 'Pasta': 125}
    

    Each value can be recovered through the respective key.
    Example:

    In [62]:
    print(dd["Meat"])
    
    300
    
    

    New elements can be added to the dictionary by adding a new key and a new value. Analogously, each key-value couple can be removed with the instruction "del".
    Example:

    In [63]:
    diet["Salad"]="How much as you like!"
    diet
    
    Out[63]:
    {'Meat': 300, 'Salad': 'How much as you like!', 'Pasta': 125, 'Fruit': 150}
    
    In [68]:
    del diet["Meat"]
    diet
    
    Out[68]:
    {'Pasta': 125, 'Fruit': 150}
    

    Methods for the dictionaries

    Like for the lists, there are special methods for the dictionaries too. The following are the most important ones, but there are many more:
    • clear():
      erases all the elements in the dictionaries;
    • keys():
      returns a set with all the keys in the dictionary;
    • values():
      returns a set with all the values in the dictionary;
    • items():
      returns a set of tuples containing the key-value couples for each element of the dictionary;

    Examples:

    In [73]:
    diet={"Pasta": 300, "Fruit": 200, "Meat": 200}
    diet.keys()
    
    Out[73]:
    dict_keys(['Meat', 'Pasta', 'Fruit'])
    
    In [74]:
    diet.values()
    
    Out[74]:
    dict_values([200, 300, 200])
    
    In [75]:
    diet.items()
    
    Out[75]:
    dict_items([('Meat', 200), ('Pasta', 300), ('Fruit', 200)])
    

    The operator in can be used to check whether a key (or values, etc.) belongs to the dictionary.
    Example:

    In [86]:
    "Meat" in diet.keys()
    
    Out[86]:
    True
    
    In [87]:
    "Salad" in diet.values()
    
    Out[87]:
    False
    
    In [88]:
    diet.clear()
    diet
    
    Out[88]:
    {}
    

    Note:
    In python 2.7, the methods keys(), values(), etc. returned a list, instead of a set. If one wants to get a list with the keys (or values, etc.) it is possible to use the function list to convert the set to a list.
    Example:

    In [90]:
    diet={1:10, 2:20, 3:30}
    mylist=list(diet.keys())
    mylist
    
    Out[90]:
    [1, 2, 3]
    

    Language syntax

    if

    if cond1:
       ...
    elif cond2:
       ...
    else:
       ...
    
    Notice that:
    • the number of elif which may appear is unlimited;
    • the final else is NOT mandatory!

    Example:

    In [91]:
    if 1==2:
       print("False")
    elif 1==3:
       print("False")
    else:
       print("True!")
    
    True!
    
    

    Conditional operators

    The following operators can be used to evaluate the conditions:
    • ==: equality;
    • >, <b><, >=, <b><=: greater than, lesser than, greater or equal, lesser or equal;
    • != : inequality.

    for

    for var in sequence:
       ...
    
    In [11]:
    for var in "aeiou":
        print(var)
    
    a
    e
    i
    o
    u
    
    

    Quite useful for the for construct is the function range(start,stop,jump), which returns a list of integers beginning from "start" up to "stop"-1, with jumps of "jump".
    Example: computes and prints the sum of the first 20 even numbers...

    In [92]:
    mysum=0
    for i in range(2,21,2):
        mysum=mysum+i
    print(mysum)
    
    110
    
    

    Remarkably, python can make a loop on two or more list at the same time, by taking the numbers as couples, triplets, and so on, through the function zip(list1, list2, etc.), which takes the elements of the various lists one by one and returns those as tuples.
    Example:

    In [4]:
    for a,b in zip([1,2,3],['a','b','c']):
        print(a, b)
    
    1 a
    2 b
    3 c
    
    

    We may obtain the same effect through the method items of dictionaries, which returns the tuple key-value.
    Example:

    In [95]:
    diet={"Pasta": 350, "Meat": 200, "Eggs": 80, "Fruit": 250}
    for food, calories in diet.items():
        print("100 grams of ", food, "contains ", calories, " calories")
    
    100 grams of  Meat contains  200  calories
    100 grams of  Pasta contains  350  calories
    100 grams of  Eggs contains  80  calories
    100 grams of  Fruit contains  250  calories
    
    

    while

    while (condition):
       ...
    

    Example: adds up the odd numbers between 1 and 21...

    In [96]:
    x=1
    sum=0
    while ( x <= 21 ):
        sum=sum+x
        x=x+2
    print(sum)
    
    121
    
    

    A complete example: the bubble-sort

    Example:

    In [97]:
    mylist=[0.5, 0.8, 0.3, 1.2, 0.2, 0.1]
    print("Initial list: ", mylist)
    list_len=len(mylist)    # Computes the lenght of the list
    num_elem=0
    while ( num_elem < list_len ):
        # Finds the minimum between the remaining elements in the list
        xmin=mylist[num_elem]
        xpos=num_elem
        for i in range(num_elem,list_len):
            if ( mylist[i] < xmin ):
                xmin=mylist[i]
                xpos=i
        print("Minimum among the elements of the list between ", num_elem, " and ", list_len - 1, ": ", xmin, " at position: ", xpos)
        # Swaps the current value in the list with the minimum
        if ( num_elem != xpos ):
            temp=mylist[num_elem]
            mylist[num_elem]=xmin
            mylist[xpos]=temp
        # Prints the partially ordinated list
        print("Partially ordered list: ", mylist)
        num_elem=num_elem+1
    print("Final, sorted, list: ", mylist)
    
    Initial list:  [0.5, 0.8, 0.3, 1.2, 0.2, 0.1]
    Minimum among the elements of the list between  0  and  5 :  0.1  at position:  5
    Partially ordered list:  [0.1, 0.8, 0.3, 1.2, 0.2, 0.5]
    Minimum among the elements of the list between  1  and  5 :  0.2  at position:  4
    Partially ordered list:  [0.1, 0.2, 0.3, 1.2, 0.8, 0.5]
    Minimum among the elements of the list between  2  and  5 :  0.3  at position:  2
    Partially ordered list:  [0.1, 0.2, 0.3, 1.2, 0.8, 0.5]
    Minimum among the elements of the list between  3  and  5 :  0.5  at position:  5
    Partially ordered list:  [0.1, 0.2, 0.3, 0.5, 0.8, 1.2]
    Minimum among the elements of the list between  4  and  5 :  0.8  at position:  4
    Partially ordered list:  [0.1, 0.2, 0.3, 0.5, 0.8, 1.2]
    Minimum among the elements of the list between  5  and  5 :  1.2  at position:  5
    Partially ordered list:  [0.1, 0.2, 0.3, 0.5, 0.8, 1.2]
    Final, sorted, list:  [0.1, 0.2, 0.3, 0.5, 0.8, 1.2]
    
    

    Input-Output

    It is fundamental for our aims that a program can receive input for a variable or prints the results in output or on a file. We have already seen the print instruction in its most elementary form to print variables, lists, etc.
    The instruction:
    print(elem1, elem2, elem3, ecc., sep=" ", end="\n")

    prints an ensemble of values separated by commas, after converting them into strings!. The parameters sep and end are optional and indicates the separator to use when printing several values (default: a blank) and how to terminate the line (default: new-line!).
    Example: (note how, though there is no blank between "for", a, "years", the blanks are inserted due to the default value of "sep"!)

    In [98]:
    a=100
    print("Best wishes for", a, "years...")
    
    Best wishes for 100 years...
    
    

    print always produces a carriage-return unless we use end= something.
    Example: prints the Pythagorean table...

    In [99]:
    for i in range(1,11):
        for j in range(1,11):
            print(i * j,end=" ")
        print()
    
    1 2 3 4 5 6 7 8 9 10 
    2 4 6 8 10 12 14 16 18 20 
    3 6 9 12 15 18 21 24 27 30 
    4 8 12 16 20 24 28 32 36 40 
    5 10 15 20 25 30 35 40 45 50 
    6 12 18 24 30 36 42 48 54 60 
    7 14 21 28 35 42 49 56 63 70 
    8 16 24 32 40 48 56 64 72 80 
    9 18 27 36 45 54 63 72 81 90 
    10 20 30 40 50 60 70 80 90 100 
    
    

    Operator %

    The operator % helps to build up a string by substituting suitable formats with the values of the variables.
    Example:

    In [100]:
    mystring="I ate %d eggs and %d grams of pasta..." % (3, 100)
    print(mystring)
    
    I ate 3 eggs and 100 grams of pasta...
    
    
    The available formats are:
    • %f: real number;
    • %e: real number in exponential notation (ex. 1.e-3);
    • %d: whole number;
    • %c: character;
    • %s: string;
    • %%: prints "%"

    One may use numerical values between "%" and the format ("f", "d", etc.) to delimit the width of the field to print!
    Example:

    In [102]:
    var=100
    print("Let the number stay in a fairly large space: %10d" % var)
    
    Let the number stay in a fairly large space:        100
    
    

    A negative number aligns to the left.
    Example: the Pythagorean table above, a little bit nicer...

    In [29]:
    for i in range(1,11):
        for j in range(1,11):
            print("%-4d" % (i * j),end=" ")
        print()
    
    1    2    3    4    5    6    7    8    9    10   
    2    4    6    8    10   12   14   16   18   20   
    3    6    9    12   15   18   21   24   27   30   
    4    8    12   16   20   24   28   32   36   40   
    5    10   15   20   25   30   35   40   45   50   
    6    12   18   24   30   36   42   48   54   60   
    7    14   21   28   35   42   49   56   63   70   
    8    16   24   32   40   48   56   64   72   80   
    9    18   27   36   45   54   63   72   81   90   
    10   20   30   40   50   60   70   80   90   100  
    
    
    A symbol
    *

    in between "%" and the format indicates a variable width, which is to be specified among the variables.
    Example:

    In [104]:
    mywidth=10
    string1=">>>"
    string2="<<<"
    print("We are finally at %*sthis%-*s point!" % (mywidth, string1, mywidth, string2))
    
    We are finally at        >>>this<<<        point!
    
    

    Function input(string)

    With this function you can read an input from the keyboard. Note that variable is always read as a string, therefore it must be converted to a different type, if we need it!
    Example: solution of a second degree equation...

    In [105]:
    print("Solution of the equation: a*x^2 + b*x + c = 0")
    a = input("Insert a: ")
    b = input("Insert b: ")
    c = input("Insert c: ")
    aa=float(a)
    bb=float(b)
    cc=float(c)
    print("Solutions:")
    print("x1 = ", (-bb+((bb*bb-4*aa*cc)**0.5))/(2*aa))
    print("x2 = ", (-bb-((bb*bb-4*aa*cc)**0.5))/(2*aa))
    
    Solution of the equation: a*x^2 + b*x + c = 0
    Insert a: 2.0
    Insert b: -1.0
    Insert c: 3.0
    Solutions:
    x1 =  (0.25000000000000006+1.1989578808281798j)
    x2 =  (0.24999999999999992-1.1989578808281798j)
    
    

    Files

    Often we will read large amounts of data from files and/or we will need to write data to files.
    As usual, the first thing to do is to open a file for reading or writing:
    object = open( file_name, access_method )
    
    where:
    • file_name is a string containing the file name;
    • access method can be:
      • "r": read
      • "w": write
      • "a": append to the end of the file


    When all the read/write operations are ended, the file can be closed with the method close().
    After opening the file, the rows can be read with the method readline(), which returns a string (newline included!) from the file. Notice that when we get to the end of the file, an empty string "" is returned.
    Example:

    In [106]:
    f=open("test.dat","r")
    str=" "
    while str != "":
       str=f.readline()
       print(str,end="")
    f.close()
    
    This is an example of "file"...
    The rows are read one by one
    and written on the screen...
    
    
    Note the
    print(str,end="")

    without which some additional newline would be printed, because it is read with the string from the file!

    The method readlines() is often easier to use because it returns a list containing all the lists read from the lines of the file.
    Example:

    In [107]:
    f=open("test.dat","r")
    for linea in f.readlines():
       print(linea,end="")
    
    This is an example of "file"...
    The rows are read one by one
    and written on the screen...
    
    

    The method write(string) writes a string on a file (note that it is impossible to write numbers directly!).
    Example:

    In [108]:
    f=open("test_output.dat","w")
    for i in range(10):
       f.write( "%d \t %f\n" % ( i+1, (i+1)**2.0 ) )
    f.close()
    

    How do we read the date just written in the file?
    The best thing to do is to read the data as strings and then to convert them in numbers through the conversion functions. This is the most flexible way to read data from files. We will see as the numpy library has functions to read numerical data directly from the files, although this is not always efficient if the file has been written in a sofisticated way.
    Example:

    In [109]:
    f=open("test_output.dat","r")
    for stringa in f.readlines():
        vals=stringa.split("\t")
        i=int(vals[0])
        i2=float(vals[1])
        i3=i*i
        print(i, "\t", i2, "\t", i3)
    f.close()
    
    1 	 1.0 	 1
    2 	 4.0 	 4
    3 	 9.0 	 9
    4 	 16.0 	 16
    5 	 25.0 	 25
    6 	 36.0 	 36
    7 	 49.0 	 49
    8 	 64.0 	 64
    9 	 81.0 	 81
    10 	 100.0 	 100
    
    

    Functions

    We have seen how to use functions in python by including the modules where they are defined. We can of course define functions created by ourselves, collect them in a module and import the module when needed.
    To define a function:
    def function_name( parameters ):
        ...
        return parameter
    

    defines a function with a name, a list of arguments and returns one or more parameters!
    Of course, returning a value is not mandatory
    Example: defines a (recursive) function to compute the factorial if a integer number...

    In [110]:
    def fact(n):
        if n == 1:
            return 1
        else:
            return n * fact(n-1)
    
    print(fact(4))
    print(fact(100))
    
    24
    93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
    
    

    As we said, it is possible to return more than a single value, or no value at all.
    Example:

    In [111]:
    # Function which prints a string n-times; it does NOT return any value
    def print_string(mystring,n):
        print(mystring * n,end="")
        print()
    
    print_string("Ciao!", 10)
    
    # Function which returns two lists, one with the numbers from 1 to n, the other one with their squares
    def double_list(n):
        nums=range(n)
        list1=[]
        list2=[]
        for i in nums:
            list1.append(i+1)
            list2.append((i+1)**2.0)
        return list1, list2
    
    l1, l2 = double_list(10)
    print(l1, l2)
    
    Ciao!Ciao!Ciao!Ciao!Ciao!Ciao!Ciao!Ciao!Ciao!Ciao!
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0, 81.0, 100.0]
    
    

    It is possible to define functions with optional parameters, namely values that, if not specified, assume some default values.
    Example:

    In [113]:
    def print_string(mystring,n=1):
        print(mystring * n,end="")
        print()
    
    print_string("ok!")
    print_string("Ciao",10)
    
    ok!
    CiaoCiaoCiaoCiaoCiaoCiaoCiaoCiaoCiaoCiao
    
    

    It is also possible to change the order of the parameters in the function call, if parameter=value is specified in the call.
    Example:

    In [114]:
    print_string(n=5,mystring="Ok! ")
    
    Ok! Ok! Ok! Ok! Ok! 
    
    
    In [ ]: