Introduction à Python (Python 3!)

Joseph Salmon : [email protected]

Adapté du travail de

Installation

Lancer un programme Python

  • Un fichier python termine par ".py":

      mon_programme.py
  • Toutes les lignes d'un fichier Python sont excécutées sauf les lignes qui commencent par le symbole # qui sont alors des commentaires.

  • Pour lancer le programme depuis une ligne de commande ou un terminal:

      $ python mon_programme.py

Exemple: il faut d'abord télécharger le fichier hello-world.py dans un dossier scripts/ . Ce fichier est disponible ici: http://josephsalmon.eu/enseignement/Montpellier/HMMA238/hello-world.py

In [1]:
ls scripts/hello-world.py
scripts/hello-world.py
In [2]:
cat scripts/hello-world.py
#!/usr/bin/env python
"""First function ever."""
print("Ciao World!")
In [3]:
! python ./scripts/hello-world.py
Ciao World!

Commencer une ligne par ! dans jupyter notebook/ipython permet de lancer une commande UNIX. Dans un notebook, on peut aussi simplement lancer la fonction avec la commande run

In [4]:
run ./scripts/hello-world.py
Ciao World!

L'interpréteur Python (mode intéractif)

L'interpréteur Python se lance avec la commande python.

IPython

IPython est un shell interactif beaucoup plus avancé.

Il permet notamment de:

  • mémoriser les commandes lancées précédemment avec les flèches (haut et bas).
  • auto-complétion avec Tab.
  • édition de code inline
  • accès simple à la doc
  • debug

Remarque: l'option ipython --pylab sera utile pour la gestion des images...

Jupyter notebook

Jupyter notebook comme Mathematica, Matlab ou Maple dans une page web.

Pour lancer jupyter notebook $ jupyter notebook

depuis un dossier où seront stockés les notebooks (fichiers *.ipynb), ou bien un dossier parent.

Pour le cas des salles machines de l'université de Montpellier, cf. http://josephsalmon.eu/enseignement/Montpellier/HLMA310/IntroPython.pdf , page 13

Les nombres

In [5]:
2 + 2 + 1 # commentaire
Out[5]:
5
In [6]:
a = 4
print(a)
print(type(a))
4
<class 'int'>

Les noms de variable peuvent contenir a-z, A-Z, 0-9 et quelques caractères spéciaux tels que _ mais commencent toujours par une lettre.

Par convention les noms de variables sont en minuscule.

Quelques noms de variable ne sont pas autorisés car déjà utilisés par le langage:

and, as, assert, break, class, continue, def, del, elif, else, except, 
exec, finally, for, from, global, if, import, in, is, lambda, not, or,
pass, print, raise, return, try, while, with, yield
In [7]:
int a = 1;  # code C ... produit donc une erreur en Python
  File "<ipython-input-7-294c5cf2bb21>", line 1
    int a = 1;  # code C ... produit donc une erreur en Python
        ^
SyntaxError: invalid syntax
In [8]:
c = 2.1  # nombre flottant
print(type(c))
<class 'float'>
In [9]:
a = 1.5 + 1j  # nombre complexe
print(a.real)
print(a.imag)
print(1j)
print(a)
print(a + 1j)
print(1j * 1j)
print(type(a))
1.5
1.0
1j
(1.5+1j)
(1.5+2j)
(-1+0j)
<class 'complex'>
In [10]:
type(1j * 1j)
Out[10]:
complex
In [11]:
3 < 4  # bool
Out[11]:
True
In [12]:
1 < 3 < 5
Out[12]:
True
In [13]:
3 < 2
Out[13]:
False
In [14]:
test = (3 > 4)
print(test)
False
In [15]:
type(test)
Out[15]:
bool
In [16]:
print(7 * 3.)  # int x float -> float
print(type(7 * 3.))
21.0
<class 'float'>
In [17]:
2 ** 10  # exposant, attention pas ^
Out[17]:
1024
In [18]:
8 % 3  # reste de la division euclidienne (modulo)
Out[18]:
2

Attention !

In [19]:
3 / 2  # float par défaut
Out[19]:
1.5
In [20]:
3 // 2
Out[20]:
1

La bibliothèque standard et ses modules

  • Les fonctions Python sont organisées par modules
  • Bibliothèque standard Python (Python Standard Library) : collection de modules donnant accès à des fonctionnalités de bases : appels au système d'exploitation, gestion des fichiers, gestion des chaînes de caractères, interface réseau, etc.

Références

Utilisation des modules

  • Un module doit être importé avant de pouvoir être utilisé, exemple :
In [21]:
import math
  • Le module math peut maintenant être utilisé dans la suite du programme :
In [22]:
import math
x = math.cos(2 * math.pi)
print(x)
1.0

Ou bien en important que les fonctions dont on a besoin ce qui peut être plus claire pour la suite

In [23]:
from math import cos, pi
x = cos(2 * pi)
print(x)
1.0

Méthode déconseillé: charger toutes les fonctions d'un module (avec le risque de redéfinir des fonctions sans s'en rendre compte).

In [24]:
from math import *
tanh(1)
Out[24]:
0.7615941559557649

Méthode courante: donner un nom abrégé au module (on verra des abréviations classique: np, pd, sns, plt, skl, etc.)

In [25]:
import math as m
print(m.cos(1.))
0.5403023058681398

Connaitre le contenu d'un module

  • Une fois un module importé on peut lister les symboles disponibles avec la fonction dir:
In [26]:
import math
print(dir(math))
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
  • Pour accéder à l'aide : help
In [27]:
help(math.log)
Help on built-in function log in module math:

log(...)
    log(x[, base])
    
    Return the logarithm of x to the given base.
    If the base not specified, returns the natural logarithm (base e) of x.

  • Dans IPython ou en Python on peut faire:
In [28]:
math.log?
In [29]:
math.log(10) 
Out[29]:
2.302585092994046
In [30]:
math.log(10, 2)
Out[30]:
3.3219280948873626
In [31]:
math.ceil(2.5)
Out[31]:
3
  • help peut être aussi utilisée sur des modules :
In [32]:
help(math)
Help on module math:

NAME
    math

MODULE REFERENCE
    https://docs.python.org/3.6/library/math
    
    The following documentation is automatically generated from the Python
    source files.  It may be incomplete, incorrect or include features that
    are considered implementation detail and may vary between Python
    implementations.  When in doubt, consult the module reference at the
    location listed above.

DESCRIPTION
    This module is always available.  It provides access to the
    mathematical functions defined by the C standard.

FUNCTIONS
    acos(...)
        acos(x)
        
        Return the arc cosine (measured in radians) of x.
    
    acosh(...)
        acosh(x)
        
        Return the inverse hyperbolic cosine of x.
    
    asin(...)
        asin(x)
        
        Return the arc sine (measured in radians) of x.
    
    asinh(...)
        asinh(x)
        
        Return the inverse hyperbolic sine of x.
    
    atan(...)
        atan(x)
        
        Return the arc tangent (measured in radians) of x.
    
    atan2(...)
        atan2(y, x)
        
        Return the arc tangent (measured in radians) of y/x.
        Unlike atan(y/x), the signs of both x and y are considered.
    
    atanh(...)
        atanh(x)
        
        Return the inverse hyperbolic tangent of x.
    
    ceil(...)
        ceil(x)
        
        Return the ceiling of x as an Integral.
        This is the smallest integer >= x.
    
    copysign(...)
        copysign(x, y)
        
        Return a float with the magnitude (absolute value) of x but the sign 
        of y. On platforms that support signed zeros, copysign(1.0, -0.0) 
        returns -1.0.
    
    cos(...)
        cos(x)
        
        Return the cosine of x (measured in radians).
    
    cosh(...)
        cosh(x)
        
        Return the hyperbolic cosine of x.
    
    degrees(...)
        degrees(x)
        
        Convert angle x from radians to degrees.
    
    erf(...)
        erf(x)
        
        Error function at x.
    
    erfc(...)
        erfc(x)
        
        Complementary error function at x.
    
    exp(...)
        exp(x)
        
        Return e raised to the power of x.
    
    expm1(...)
        expm1(x)
        
        Return exp(x)-1.
        This function avoids the loss of precision involved in the direct evaluation of exp(x)-1 for small x.
    
    fabs(...)
        fabs(x)
        
        Return the absolute value of the float x.
    
    factorial(...)
        factorial(x) -> Integral
        
        Find x!. Raise a ValueError if x is negative or non-integral.
    
    floor(...)
        floor(x)
        
        Return the floor of x as an Integral.
        This is the largest integer <= x.
    
    fmod(...)
        fmod(x, y)
        
        Return fmod(x, y), according to platform C.  x % y may differ.
    
    frexp(...)
        frexp(x)
        
        Return the mantissa and exponent of x, as pair (m, e).
        m is a float and e is an int, such that x = m * 2.**e.
        If x is 0, m and e are both 0.  Else 0.5 <= abs(m) < 1.0.
    
    fsum(...)
        fsum(iterable)
        
        Return an accurate floating point sum of values in the iterable.
        Assumes IEEE-754 floating point arithmetic.
    
    gamma(...)
        gamma(x)
        
        Gamma function at x.
    
    gcd(...)
        gcd(x, y) -> int
        greatest common divisor of x and y
    
    hypot(...)
        hypot(x, y)
        
        Return the Euclidean distance, sqrt(x*x + y*y).
    
    isclose(...)
        isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool
        
        Determine whether two floating point numbers are close in value.
        
           rel_tol
               maximum difference for being considered "close", relative to the
               magnitude of the input values
            abs_tol
               maximum difference for being considered "close", regardless of the
               magnitude of the input values
        
        Return True if a is close in value to b, and False otherwise.
        
        For the values to be considered close, the difference between them
        must be smaller than at least one of the tolerances.
        
        -inf, inf and NaN behave similarly to the IEEE 754 Standard.  That
        is, NaN is not close to anything, even itself.  inf and -inf are
        only close to themselves.
    
    isfinite(...)
        isfinite(x) -> bool
        
        Return True if x is neither an infinity nor a NaN, and False otherwise.
    
    isinf(...)
        isinf(x) -> bool
        
        Return True if x is a positive or negative infinity, and False otherwise.
    
    isnan(...)
        isnan(x) -> bool
        
        Return True if x is a NaN (not a number), and False otherwise.
    
    ldexp(...)
        ldexp(x, i)
        
        Return x * (2**i).
    
    lgamma(...)
        lgamma(x)
        
        Natural logarithm of absolute value of Gamma function at x.
    
    log(...)
        log(x[, base])
        
        Return the logarithm of x to the given base.
        If the base not specified, returns the natural logarithm (base e) of x.
    
    log10(...)
        log10(x)
        
        Return the base 10 logarithm of x.
    
    log1p(...)
        log1p(x)
        
        Return the natural logarithm of 1+x (base e).
        The result is computed in a way which is accurate for x near zero.
    
    log2(...)
        log2(x)
        
        Return the base 2 logarithm of x.
    
    modf(...)
        modf(x)
        
        Return the fractional and integer parts of x.  Both results carry the sign
        of x and are floats.
    
    pow(...)
        pow(x, y)
        
        Return x**y (x to the power of y).
    
    radians(...)
        radians(x)
        
        Convert angle x from degrees to radians.
    
    sin(...)
        sin(x)
        
        Return the sine of x (measured in radians).
    
    sinh(...)
        sinh(x)
        
        Return the hyperbolic sine of x.
    
    sqrt(...)
        sqrt(x)
        
        Return the square root of x.
    
    tan(...)
        tan(x)
        
        Return the tangent of x (measured in radians).
    
    tanh(...)
        tanh(x)
        
        Return the hyperbolic tangent of x.
    
    trunc(...)
        trunc(x:Real) -> Integral
        
        Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic method.

DATA
    e = 2.718281828459045
    inf = inf
    nan = nan
    pi = 3.141592653589793
    tau = 6.283185307179586

FILE
    /home/jo/anaconda3/lib/python3.6/lib-dynload/math.cpython-36m-x86_64-linux-gnu.so


EXERCICE : Écrire un code qui calcule la première puissance de 2 supérieure à un nombre $n$

In [33]:
n = 12345
# XXX 

Fractions

In [34]:
import fractions
a = fractions.Fraction(2, 3)
b = fractions.Fraction(1, 2)
print(a + b)
7/6
  • On peut utiliser isinstance pour tester les types des variables :
In [35]:
print(type(a))
print(isinstance(a, fractions.Fraction))
<class 'fractions.Fraction'>
True
In [36]:
a = fractions.Fraction(1, 1)
print(isinstance(a, int))
False

Type casting (conversion de type)

In [37]:
x = 1.5
print(x, type(x))
1.5 <class 'float'>
In [38]:
x = int(x)
print(x, type(x))
1 <class 'int'>
In [39]:
z = complex(x)
print(z, type(z))
(1+0j) <class 'complex'>

Attention: tout de même:

In [40]:
x = float(z)
print(x, type(x))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-7002fbe22da4> in <module>()
----> 1 x = float(z)
      2 print(x, type(x))

TypeError: can't convert complex to float

Operateurs et comparaisons

In [41]:
1 + 2, 1 - 2, 1 * 2, 1 / 2  # + - / * sur des entiers
Out[41]:
(3, -1, 2, 0.5)
In [42]:
1.0 + 2.0, 1.0 - 2.0, 1.0 * 2.0, 1.0 / 2.0  # + - / * sur des flottants
Out[42]:
(3.0, -1.0, 2.0, 0.5)
In [43]:
# Division entière
3.0 // 2.0
Out[43]:
1.0
In [44]:
# Attention ** et pas ^ comme dans d'autres langages
2 ** 2
Out[44]:
4
  • Opérations booléennes en anglais and, not, or.
In [45]:
True and False
Out[45]:
False
In [46]:
not False
Out[46]:
True
In [47]:
True or False
Out[47]:
True
  • Comparisons >, <, >= (plus grand ou égal), <= (inférieur ou égal), == equalité, is identique.
In [48]:
2 > 1, 2 < 1
Out[48]:
(True, False)
In [49]:
2 > 2, 2 < 2
Out[49]:
(False, False)
In [50]:
2 >= 2, 2 <= 2
Out[50]:
(True, True)
In [51]:
2 != 3  # différent de
Out[51]:
True
In [52]:
not 2 == 3  # négation
Out[52]:
True

Conteneurs: Chaînes de caractères, listes et dictionnaires

Chaines de caractères (Strings)

In [53]:
s = 'Ciao Ciao!'
# ou avec " "
s = "Ciao Ciao!"
print(s)
print(type(s))
Ciao Ciao!
<class 'str'>

Attention: les indices commencent à 0!

On peut extraire une sous-chaine avec la syntaxe [start:stop], qui extrait les caractères entre start (inclus) et stop (exclu) :

In [54]:
s[0]  # premier élément
Out[54]:
'C'
In [55]:
s[-1]  # dernier élément
Out[55]:
'!'
In [56]:
s[1:5]
Out[56]:
'iao '
In [57]:
start, stop = 1, 5
print(s[start:stop])
print(len(s[start:stop]))
iao 
4
In [58]:
print(stop - start)
4
In [59]:
print(start)
print(stop)
1
5

Pour la curiosité: les chaînes de caractères sont "compliquées", surtout pour les langues, comme le français, qui ont des accents, cédilles, etc.

Voir: unicode et utf8, etc. http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/ pour

On peut omettre start ou stop. Dans ce cas les valeurs par défaut sont respectivement 0 et la fin de la chaine.

In [60]:
s[:5]  # 5 premières valeurs
Out[60]:
'Ciao '
In [61]:
s[2:]  # de l'entrée d'indice 6 à la fin
Out[61]:
'ao Ciao!'
In [62]:
print(len(s[5:]))  # en anglais length = longeur
print(len(s) - 5)
5
5
In [63]:
s[-3:]  # les 6 derniers
Out[63]:
'ao!'

Il est aussi possible de définir le step (pas d'avancement) avec la syntaxe [start:stop:step] (la valeur par défaut de step est 1):

In [64]:
print(s[1::2])
print(s[0::2])
ioCa!
Ca io

EXERCICE : A partir des lettres de l'alphabet, générer par une operation de slicing la chaîne de charactère *cfilorux*

In [65]:
import string
alphabet = string.ascii_lowercase
print(alphabet)
abcdefghijklmnopqrstuvwxyz
In [66]:
# XXX

Mise en forme de chaînes de caractères

In [67]:
print("str1", "str2", "str3")  # print ajoute des espaces entre les chaînes
str1 str2 str3
In [68]:
print("str1", 1.0, False, -1j)  # print convertit toutes les variables en chaînes
str1 1.0 False (-0-1j)
In [69]:
print("str1" + "str2" + "str3") # pour concatener ("coller ensemble") utiliser le symbole +
str1str2str3
In [70]:
print("str1" * 3)  # répétition
str1str1str1
In [71]:
a = 1.0000000002
b = 1.00031e2
c= 136869689
print("val = {}".format(a))
print("val = {}".format(b))

print("val = {0:1.5e}".format(a))
print("val = {0:1.5e}".format(b))

print("val = {0:1.15f}".format(a))

print("val = {:3d}".format(c))
print("val = {:13d}".format(c))
print("val = {:6d}".format(c))
val = 1.0000000002
val = 100.031
val = 1.00000e+00
val = 1.00031e+02
val = 1.000000000200000
val = 136869689
val =     136869689
val = 136869689
In [72]:
# Plus avancé
print("val = {0:1.15f},val2={1:1.15f}".format(a, b))
val = 1.000000000200000,val2=100.031000000000006
In [73]:
s = "Le nombre {0:s} est égal à {1:1.111}"
print(s.format("pi", math.pi))
# print s % ("e", math.exp(1.))
Le nombre pi est égal à 3.141592653589793115997963468544185161590576171875

Listes

Les listes sont très similaires aux chaînes de caractères sauf que les éléments peuvent être de n'importe quel type.

Une syntaxe possible pour créer des listes est [..., ..., ...]

In [74]:
l = [1, 2, 3, 4]
print(type(l))
print(l)
<class 'list'>
[1, 2, 3, 4]

Exemples de slicing:

In [75]:
print(l[1:3])
print(l[::2])
[2, 3]
[1, 3]

Attention: On commence à indexer à 0!

In [76]:
l[0]
Out[76]:
1

On peut mélanger les types:

In [77]:
l = [1, 'a', 1.0, 1-1j]
print(l)
[1, 'a', 1.0, (1-1j)]

On peut faire des listes de listes (par exemple pour décrire un arbre...)

In [78]:
list_of_list = [1, [2, [3, [4, [5]]]]]
list_of_list
Out[78]:
[1, [2, [3, [4, [5]]]]]
In [79]:
arbre = [1, [2, 3]]
print(arbre)
[1, [2, 3]]

La fonction range pour générer une liste d'entiers:

In [80]:
start, stop, step = 10, 30, 2
print(range(start, stop, step))
print(range(10, 30, 2))
print(list(range(10, 30, 2)))
range(10, 30, 2)
range(10, 30, 2)
[10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

Intération de $n-1$ à $0$

In [81]:
n = 10
print(range(n-1, -1, -1))
range(9, -1, -1)
In [82]:
range(-10, 10)
Out[82]:
range(-10, 10)
In [83]:
# convertir une chaine de caractère en liste
s = "zabcda"
l2 = list(s)
print(l2)
['z', 'a', 'b', 'c', 'd', 'a']
In [84]:
# tri (en anglais ce dit "sort")
l2.sort()
print(l2)
l2.sort(reverse=True)
print(l2)
print(l2[::-1])
['a', 'a', 'b', 'c', 'd', 'z']
['z', 'd', 'c', 'b', 'a', 'a']
['a', 'a', 'b', 'c', 'd', 'z']

Attention: l2.sort() ne renvoie rien, c'est-à-dire que l'on renvoie None

In [85]:
out = l2.sort()
print(out)
None

Pour renvoyer une nouvelle liste triée:

In [86]:
out = sorted(l2)
print(out)
out2 = sorted(l2, reverse=True)
print(out2)
['a', 'a', 'b', 'c', 'd', 'z']
['z', 'd', 'c', 'b', 'a', 'a']

Ajout, insertion, modifier, et enlever des éléments d'une liste:

In [87]:
# Création d'une liste vide
l = []  # ou encore: l = list()

# Ajout d'éléments par la droite avec `append`
m = l.append("A")
l.append("d")
l.append("d")

print(m)
print(l)
None
['A', 'd', 'd']

Concatenation de listes avec l'opérateur "+"

In [88]:
lll = [1, 2, 3]
mmm = [4, 5, 6]
print (lll + mmm)  
[1, 2, 3, 4, 5, 6]

Attention: différent de lll.append(mmm)

In [89]:
lll.append(mmm)
print(lll)
[1, 2, 3, [4, 5, 6]]
In [90]:
print(mmm * 3)
[4, 5, 6, 4, 5, 6, 4, 5, 6]

On peut modifier une liste par assignation:

In [91]:
l[1] = "p"
l[2] = "p"
print(l)
['A', 'p', 'p']
In [92]:
l[1:3] = ["d", "d"]
print(l)
['A', 'd', 'd']

Insertion à un index donné avec insert

In [93]:
l.insert(0, "i")
l.insert(1, "n")
l.insert(2, "s")
l.insert(3, "e")
l.insert(4, "r")
l.insert(5, "t")

print(l)
['i', 'n', 's', 'e', 'r', 't', 'A', 'd', 'd']

Suppression d'un élément avec remove

In [94]:
l.remove("A")
print(l)
['i', 'n', 's', 'e', 'r', 't', 'd', 'd']
In [95]:
ll = [1, 2, 3, 2]
print(ll)
ll.remove(2)
print(ll)
[1, 2, 3, 2]
[1, 3, 2]
In [96]:
print(2 in ll)
print(5 in ll)

print(l.index('r'))
print(l.index('t'))
True
False
4
5

Suppression d'un élément à une position donnée avec del:

In [97]:
del l[7]
del l[6]
print(l)
['i', 'n', 's', 'e', 'r', 't']

help(list) pour en savoir plus.

In [98]:
help(list)
Help on class list in module builtins:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      L.__reversed__() -- return a reverse iterator over the list
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      L.__sizeof__() -- size of L in memory, in bytes
 |  
 |  append(...)
 |      L.append(object) -> None -- append object to end
 |  
 |  clear(...)
 |      L.clear() -> None -- remove all items from L
 |  
 |  copy(...)
 |      L.copy() -> list -- a shallow copy of L
 |  
 |  count(...)
 |      L.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      L.extend(iterable) -> None -- extend list by appending elements from the iterable
 |  
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      L.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      L.pop([index]) -> item -- remove and return item at index (default last).
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(...)
 |      L.remove(value) -> None -- remove first occurrence of value.
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(...)
 |      L.reverse() -- reverse *IN PLACE*
 |  
 |  sort(...)
 |      L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

Tuples

  • Les tuples (n-uplets) ressemblent aux listes mais ils sont immuables : ils ne peuvent plus être modifiés une fois créés.

  • On les crée avec la syntaxe (..., ..., ...) ou simplement ..., ...:

In [99]:
point = (10, 20)
print(point, type(point))
(10, 20) <class 'tuple'>
In [100]:
point[0]
Out[100]:
10

Un tuple peut être dépilé par assignation à une liste de variables séparées par des virgules :

In [101]:
x, y = point

print("Coordonnée x : ", x)
print("Coordonnée y : ", y)
Coordonnée x :  10
Coordonnée y :  20

On ne peut pas exécuter la commande suivante sans obtenir un message d'erreur:

In [102]:
point[0] = 20
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-102-ac1c641a5dca> in <module>()
----> 1 point[0] = 20

TypeError: 'tuple' object does not support item assignment

Dictionnaires

Ils servent à stocker des données de la forme clé-valeur.

La syntaxe pour les dictionnaires est {key1 : value1, ...}:

In [103]:
params = {"parameter1": 1.0,
          "parameter2": 2.0,
          "parameter3": 3.0}

# ou bien

params = dict(parameter1=1.0, parameter2=2.0, parameter3=3.0)

print(type(params))
print(params)
<class 'dict'>
{'parameter1': 1.0, 'parameter2': 2.0, 'parameter3': 3.0}
In [104]:
print("p1 =", params["parameter1"])
print("p2 =", params["parameter2"])
print("p3 =", params["parameter3"])
p1 = 1.0
p2 = 2.0
p3 = 3.0
In [105]:
# substitution de valeur
params["parameter1"] = "A"
params["parameter2"] = "B"

# ajout d'une entrée
params["parameter4"] = "D"

print("p1 =", params["parameter1"])
print("p2 =", params["parameter2"])
print("p3 =", params["parameter3"])
print("p4 =", params["parameter4"])
p1 = A
p2 = B
p3 = 3.0
p4 = D

Suppression d'une clé:

In [106]:
del params["parameter4"]
print(params)
{'parameter1': 'A', 'parameter2': 'B', 'parameter3': 3.0}

Test de présence d'une clé

In [107]:
"parameter1" in params
Out[107]:
True
In [108]:
"parameter6" in params
Out[108]:
False
In [109]:
params["parameter6"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-109-9d26f4da51fe> in <module>()
----> 1 params["parameter6"]

KeyError: 'parameter6'

Remarque: il est bon de s'habituer aux messages d'erreurs (ici le message est clair et montre que la clef n'existe pas)

Conditions, branchements et boucles

Branchements: if, elif, else

(noter le symbole ":" à la fin de la ligne)

In [110]:
statement1 = False
statement2 = False
# statement2 = True


if statement1:
    print("statement1 is True")
elif statement2:
    print("statement2 is True")
else:
    print("statement1 and statement2 are False")
statement1 and statement2 are False

En Python l'indentation est obligatoire car elle influence l'exécution du code

Examples:

In [111]:
statement1 = statement2 = True

if statement1:
    if statement2:
        print("both statement1 and statement2 are True")
both statement1 and statement2 are True
In [112]:
# Mauvaise indentation!
if statement1:
    if statement2:
    print "both statement1 and statement2 are True"
  File "<ipython-input-112-0516d1e4e779>", line 4
    print "both statement1 and statement2 are True"
        ^
IndentationError: expected an indented block
In [113]:
statement1 = True 

if statement1:
    print("printed if statement1 is True")
    print("still inside the if block")
printed if statement1 is True
still inside the if block
In [114]:
statement1 = False

if statement1:
    print("printed if statement1 is True")
print("still inside the if block")
still inside the if block

Boucles

Boucles for:

(noter le symbole ":" à la fin de la ligne)

In [115]:
for x in [1, 2, 3]:
    print(x)
1
2
3

La boucle for itère sur les éléments de la list fournie. Par exemple:

In [116]:
for x in range(4): # par défault range commence à 0 et permet de créer le tutple (0,1,2,...,n-1)
    print(x)
0
1
2
3

Attention range(4) n'inclut pas 4 !

In [117]:
for x in range(-3,3):
    print(x)
-3
-2
-1
0
1
2
In [118]:
for word in ["calcul", "scientifique", "en", "python"]:
    print(word)
calcul
scientifique
en
python
In [119]:
for letter in "calcul":
    print(letter)
c
a
l
c
u
l

Pour itérer sur un dictionnaire::

In [120]:
for key, value in params.items():
    print(key, " = ", value)
parameter1  =  A
parameter2  =  B
parameter3  =  3.0
In [121]:
params.items()
Out[121]:
dict_items([('parameter1', 'A'), ('parameter2', 'B'), ('parameter3', 3.0)])
In [122]:
for key in params:
    print(key)
parameter1
parameter2
parameter3
In [123]:
for key in params:
    print(params[key])
A
B
3.0

Il est souvent utile d'accéder à la fois à la valeur et à l'index de l'élément. Il faut alors utiliser enumerate:

In [124]:
for idx, x in enumerate(l):
    print(idx, x)
0 i
1 n
2 s
3 e
4 r
5 t

EXERCICE : Compter le nombre d'occurences de chaque charactère dans la chaîne de caractères "HelLo WorLd!!" On renverra un dictionaire qui à la lettre associe son nombre d'occurences.

In [125]:
s = "HelLo WorLd!!"   # on pourra utiliser la fonction lower() pour obtenir les lettres en miniscules

# XXX

# solution c = dict(h=1, e=1, l=3, o=2, w=1, r=1, d=1, !=2) , à permutation prête

EXERCICE : Message codé par inversion de lettres (aussi appelé [code de César](https://fr.wikipedia.org/wiki/Chiffrement_par_d%C3%A9calage))

Proposer une manipulation qui permet de faire le codage et le décodage avec le code fournit dessous

In [126]:
code = {'e': 'a', 'l': 'm', 'o': 'e'}
# REM: on pourra utiliser par exemple le symbole +=, qui permet l'increment sur place...
s = 'Hello world!'
s_code = ''
# XXX
# solution: s_code = 'Hamme wermd!'

my_inverted_code = {value: key for key, value in code.items()}
s_decoded = ''
# XXX

# solution: s_decoded = 'Hello world!'

Compréhension de liste:

Boucles for:

In [127]:
ll = [x ** 2 for x in range(0,5)]

print(ll)

# Une version plus courte de :
ll = list()
for x in range(0, 5):
    ll.append(x ** 2)

print(ll)

# pour les gens qui font du caml, ou d'autre langages fonctionnels (en anglais map = function)
print(map(lambda x: x ** 2, range(5)))
[0, 1, 4, 9, 16]
[0, 1, 4, 9, 16]
<map object at 0x7fbe04a65320>

Boucles while:

In [128]:
i = 0

while i < 5:
    print(i)
    i = i + 1

print("OK")
0
1
2
3
4
OK

Exercice: Calculer une approximation de $\pi$ par la formule de Wallis (avec une boucle `for`)

\begin{align} \text{Formule de Wallis:}\quad \pi&= 2 \cdot\prod_{n=1}^{\infty }\left({\frac{4 n^{2}}{4 n^{2} - 1}}\right) \end{align}

Voir: https://fr.wikipedia.org/wiki/Produit_de_Wallis

In [129]:
# XXX

Fonctions

Une fonction en Python est définie avec le mot clé def, suivi par le nom de la fonction, la signature entre parenthèses (), et un : en fin de ligne

Exemples:

In [130]:
def func0():
    print("test")
In [131]:
func0()
test

Ajout d'une documentation (docstring):

In [132]:
def func1(s):
    """Affichage d'une chaine et de sa longueur."""
    print(s, "est de longueur", len(s))
In [133]:
help(func1)
Help on function func1 in module __main__:

func1(s)
    Affichage d'une chaine et de sa longueur.

In [134]:
print(func1("test"))
print(func1([1, 2, 3]))
test est de longueur 4
None
[1, 2, 3] est de longueur 3
None

Il est bien sûr généralement utile de retourner une valeur, on utilise alors return:

In [135]:
def square(x):
    """ Retourne le carré de x."""
    return x ** 2
In [136]:
print(square(4))
16

Retourner plusieurs valeurs:

In [137]:
def powers(x):
    """Retourne les premières puissances de x."""
    return x ** 2, x ** 3, x ** 4
In [138]:
print(powers(3))
x2, x3, x4 = powers(3)
print(x2, x3)
print(type(powers(3)))
out = powers(3)
print(len(out))
print(out[1])
print(out[2])
(9, 27, 81)
9 27
<class 'tuple'>
3
27
81
In [139]:
t = (3,)
print(t, type(t))
(3,) <class 'tuple'>
In [140]:
x2, x3, x4 = powers(3)
print x3
  File "<ipython-input-140-8a87a2243257>", line 2
    print x3
           ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(x3)?

Arguments par défault

Il est possible de fournir des valeurs par défaut aux paramètres:

In [141]:
def myfunc(x, p=2, verbose=False):
    if verbose:
        print("evalue myfunc avec x =", x, "et l'exposant p =", p)
    return x**p

Le paramètre verbose peut être omis:

In [142]:
myfunc(5)
Out[142]:
25
In [143]:
myfunc(5, 3)
Out[143]:
125
In [144]:
myfunc(5, verbose=True)
evalue myfunc avec x = 5 et l'exposant p = 2
Out[144]:
25

On peut expliciter les noms de variables et alors l'ordre n'importe plus:

In [145]:
myfunc(p=3, verbose=True, x=7)
evalue myfunc avec x = 7 et l'exposant p = 3
Out[145]:
343

Exercice: implémenter l'algorithme de tri quicksort

</font>

La page wikipedia décrivant l’algorithme de tri quicksort donne le pseudo-code suivant:

function quicksort('array')
   if length('array') <= 1
        return 'array'
   select and remove a pivot value 'pivot' from 'array'
   create empty lists 'less' and 'greater'
   for each 'x' in 'array'
       if 'x' <= 'pivot' then append 'x' to 'less'
       else append 'x' to 'greater'
   return concatenate(quicksort('less'), 'pivot', quicksort('greater'))

Transformer ce pseudo-code en code valide Python.

Des indices:

  • la longueur d’une liste est donnée par len(l)
  • deux listes peuvent être concaténées avec l1 + l2
  • l.pop() retire le dernier élément d’une liste

Attention: une liste est mutable...

Il vous suffit de compléter cette ébauche:

In [146]:
def quicksort(ll):
    # ...
    return 

quicksort([-2, 3, 5, 1, 3])

Classes

  • Les classes sont les éléments centraux de la programmation orientée objet

  • Classe: structure qui sert à représenter un objet et l'ensemble des opérations qui peuvent êtres effectuées sur ce dernier.

Dans Python une classe contient des attributs (variables) et des méthodes (fonctions). Elle est définie de manière analogue aux fonctions mais en utilisant le mot clé class. La définition d'une classe contient généralement un certain nombre de méthodes de classe (des fonctions dans la classe).

  • Le premier argument d'un méthode doit être self: argument obligatoire. Cet objet self est une auto-référence.
  • Certains noms de méthodes ont un sens particulier, par exemple :

Exemple

In [147]:
class Point(object):
    """Classe pour représenter un point dans le plan."""

    def __init__(self, x, y):
        """Creation d'un nouveau point en position x, y."""
        self.x = x
        self.y = y

    def translate(self, dx, dy):
        """Translate le point de dx and dy."""
        self.x += dx
        self.y += dy

    def __str__(self):
        return "Point: [{0:1.3f}, {1:1.3f}]".format(self.x, self.y) 

Pour créer une nouvelle instance de la classe:

In [148]:
p1 = Point(x=0, y=0) # appel à __init__ ;
print(p1.x)
print(p1.y)
print("{0}".format(p1))         # appel à la méthode __str__
0
0
Point: [0.000, 0.000]
In [149]:
p1.translate(dx=1, dy=1)
print(p1.translate)
print(p1)
print(type(p1))
<bound method Point.translate of <__main__.Point object at 0x7fbe04a8ef98>>
Point: [1.000, 1.000]
<class '__main__.Point'>

Pour invoquer une méthode de la classe sur une instance p de celle-ci:

In [150]:
p2 = Point(1, 1)

p1.translate(0.25, 1.5)

print(p1)
print(p2)
Point: [1.250, 2.500]
Point: [1.000, 1.000]

Remarques

  • L'appel d'une méthode de classe peut modifier l'état d'une instance particulière
  • Cela n'affecte ni les autres instances ni les variables globales

Exceptions

  • Dans Python les erreurs sont gérées à travers des "Exceptions"
  • Une erreur provoque une Exception qui interrompt l'exécution normale du programme
  • L'exécution peut éventuellement reprendre à l'intérieur d'un bloc de code try - except
  • Une utilisation typique: arrêter l'exécution d'une fonction en cas d'erreur:

      def my_function(arguments):
    
      if not verify(arguments):
          raise Expection("Invalid arguments")
    
      # et on continue

On utilise try et expect pour maîtriser les erreurs:

try:
    # normal code goes here
except:
    # code for error handling goes here
    # this code is not executed unless the code
    # above generated an error

Par exemple:

In [151]:
try:
    print("test_var")
    # genere une erreur: la variable test n'est pas définie
    print(test_var)
except:
    print("Caught an expection")
print("mais on continu...ca ne plante pas!")
test_var
Caught an expection
mais on continu...ca ne plante pas!

Pour obtenir de l'information sur l'erreur: accéder à l'instance de la classe Exception concernée:

except Exception as e:
In [152]:
try:
    print("test")
    print(testtt)    # erreur: la variable test est non définie
except Exception as e:
    print("Caught an expection:", e)
test
Caught an expection: name 'testtt' is not defined

Manipuler les fichiers sur le disque

In [153]:
import os
print(os.path.join('~', 'work', 'src'))  # permet de fonctionner sur Linux / Windows /Mac
print(os.path.join(os.getcwd(),'new_directory'))
# os.path.expanduser?
# print(os.path.expanduser(os.path.join('~', 'work', 'src')))
~/work/src
/home/jo/Documents/Mes_cours/Montpellier/HMMA238/notebooks/new_directory

Quelques liens