Initiation à Python

Cette page web est en fait un notebook, visualisé par Jupyter et dont le code est exécuté par IPython. Vous l'avez ouvert dans votre navigateur après avoir tapé dans votre console

jupyter notebook

et sélectionné le fichier initiation.ipynb.

Le texte que vous êtes en train de lire est contenu dans une cellule de type Markdown qui permet un formattage aisé du texte, y compris des formules $\LaTeX$ en ligne comme $\sum\gamma_i^2$ ou en equations séprarées: $$\frac{\ln \pi}{12}.$$

Un notebook peut donc contenir deux types de cellules:

  • Markdown
  • Code

Vous pouvez sélectionner le type de cellule dans le menu déroulant de la barre d'outils ci-dessus. En utilisant le menu Insert, vous pouvez ajouter des cellules. Les cellules de code s'exécutent en faisant Maj+Entrer. Les cellules Markdown se formattent de la même façon et on retourne à l'édition de leur contenu par un double clic.

Les fonctions

En Python, tout est dans l'indentation


In [1]:
def mafonction(a, b):
    print("Je divise")
    return a/b # indentation de l'intérieur de la fonction = on est toujours dans la fonction
print("fini de définir ma fonction") # indentation de l'extérieur de la fonction donc la fonction est finie


fini de définir ma fonction

In [2]:
mafonction(5,2)


Je divise
Out[2]:
2.5

On peut documenter ses propres fonctions.


In [3]:
def mafonction(a, b):
    """Division de a par b"""
    return a/b

In [4]:
mafonction?


Signature: mafonction(a, b)
Docstring: Division de a par b
File:      ~/Documents/Cours/initiation-python/<ipython-input-3-de019539858a>
Type:      function

Il est possible d'avoir des arguments par défaut.


In [5]:
def mafonction(a, b=2):
    """Division de a par b"""
    return a/b
print(mafonction(5))
print(mafonction(5,10))


2.5
0.5

In [6]:
mafonction?


Signature: mafonction(a, b=2)
Docstring: Division de a par b
File:      ~/Documents/Cours/initiation-python/<ipython-input-5-d8ff2f7ecb79>
Type:      function

Un peu plus complexe : on imbrique deux indentations et on a 2 arguments avec des valeurs par défaut.


In [7]:
def mafonction(a, b=2, diviser=True):
    """Division de a par b.
    Si on ne divise pas, on retourne a et b""" #on a le droit de passer à la ligne si on a ouvert 3 guillemets
    if diviser:
        return a/b
    else:
        return a,b
print(mafonction(5))
print(mafonction(5, 10))
print(mafonction(5, diviser=False))


2.5
0.5
(5, 2)

Jouer avec les chaînes de caractères

Indexation, sous-chaîne et concaténation


In [8]:
a = "coucou" #definition de l'objet. Pas besoin de donner son type
print(a) #affichage de toute la chaîne de caractères
print(a[0]) #affichage du premier élément. Attention, les indices commencent à 0
print(a[1])
print(a[-1]) #affichage du dernier élément. On utilise des entiers négatifs pour partir de la fin
print(a[1:]) #affichage à partir de l'élément 1
print(a[:3]) #jusqu'à l'élément 3 non inclu. Equivalent mais plus court que a[0:3]
print(a[:-1]) #jusqu'au dernier élément non inclu
print(a[::2]) #tous les 2 éléments. Equivalent mais plus court que a[0:len(a):2]
print(a[1:-1:3]) #à partir de l'élement 1, jusqu'au dernier élément non inclu, tous les 3 éléments


coucou
c
o
u
oucou
cou
couco
cuo
oo

In [9]:
print("cou" + "cou") #concaténation de deux chaînes de caractères
print("cou" * 2) # répétition 2 fois


coucou
coucou

Les boucles


In [10]:
#premiere boucle for. On itère directement sur les caractères de la chaîne.
for lettre in a:
    print(lettre)
    print("-") # indentation de l'intérieur de la boucle = on est toujours dans la boucle
print("c'est fini") # indentation de l'extérieur de la boucle donc la boucle est finie


c
-
o
-
u
-
c
-
o
-
u
-
c'est fini

In [11]:
for lettre in a[::-1]:
    print(lettre)


u
o
c
u
o
c

In [12]:
for i,lettre in enumerate(a): #i est l'indice de l'itération dans la boucle
    print(i,lettre)


0 c
1 o
2 u
3 c
4 o
5 u

In [13]:
for u,v in zip(a, "colibri"): #à chaque tour de boucle on prend une lettre de "coucou" et une lettre de "colibri"
    print(u+v)


cc
oo
ul
ci
ob
ur

Phrases à trous


In [12]:
b = "Je m'appelle {}."
print(b)
print(b.format("Mathieu"))


Je m'appelle {}.
Je m'appelle Mathieu.

In [13]:
print(a.format("Mathieu"))


coucou

In [14]:
b = "My name is {1}, {0} {1}."
print(b.format("James", "Bond"))


My name is Bond, James Bond.

In [15]:
b2 = "My name is {nom}, {prenom} {nom}."
print(b2.format(prenom="James", nom="Bond"))


My name is Bond, James Bond.

In [16]:
c = "Veuillez charger le fichier acquisition_t{:03d}.txt" #nombre décimal sur 3 chiffres, éventuellement complétés de zéros
print(c.format(5))
print(c.format(23))
print(c.format(328))


Veuillez charger le fichier acquisition_t005.txt
Veuillez charger le fichier acquisition_t023.txt
Veuillez charger le fichier acquisition_t328.txt

In [18]:
print(c.format(0.1))
print(c.format("hi"))


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-4059f93e68f5> in <module>()
----> 1 print(c.format(0.1))
      2 print(c.format("hi"))

ValueError: Unknown format code 'd' for object of type 'float'

Syntaxe complète des instructions de formattage, si un jour vous avez envie d'afficher un nombre hexadécimal sur 7 charactères minimum, éventuellement complété avec des symboles livre sterling, ou un nombre flottant avec 2 chiffres significatifs.

On peut aussi obtenir de l'aide sur une méthode d'un objet.


In [19]:
c.format?


Docstring:
S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
Type:      builtin_function_or_method

In [20]:
print("Veuillez charger le fichier acquisition_t%03d.txt"%5)


Veuillez charger le fichier acquisition_t005.txt

Listes


In [22]:
l = [a, b, 127, 3.14, ["James", "Bond"], c]
print(l)
print(l[0])
print(l[0][1])
print(l[0]+l[1].format(l[-2][0], l[-2][1])) # pour "déplier" tous les éléments de la liste l[-2] en tant qu'arguments de la fonction format
#possible d'écrire directement format(*l[-2])
print(l[-1].format(l[2]) + " Mr {}.".format(l[-2][-1]))


['coucou', 'My name is {1}, {0} {1}.', 127, 3.14, ['James', 'Bond'], 'Veuillez charger le fichier acquisition_t{:03d}.txt']
coucou
o
coucouMy name is Bond, James Bond.
Veuillez charger le fichier acquisition_t127.txt Mr Bond.

Il est possible de modifier les éléments d'une liste et même de changer leur type.


In [23]:
l[2] = 12
l[-2][-1] = 3
print(l[-1].format(l[2]) + " Mr {}.".format(l[-2][-1]))


Veuillez charger le fichier acquisition_t012.txt Mr 3.

In [24]:
l2 = []
for i in range(3):
    l2.append(i**2)
print(l2)


[0, 1, 4]

tuple

Comme une liste, mais avec des parenthèses au lieu de crochets. Il est interdit de modifier le contenu d'un tuple.


In [27]:
t = (a, b, 127, 3.14, ("James", "Bond"), c)
print(t)
print(t[0])
print(t[0][1])
print(t[0]+t[1].format(*t[-2]))
print(t[-1].format(t[2]) + " Mr {}.".format(t[-2][-1]))


('coucou', 'My name is {1}, {0} {1}.', 127, 3.14, ('James', 'Bond'), 'Veuillez charger le fichier acquisition_t{:03d}.txt')
coucou
o
coucouMy name is Bond, James Bond.
Veuillez charger le fichier acquisition_t127.txt Mr Bond.

In [28]:
t[2] = 12


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-28-68e0e9062cd8> in <module>()
----> 1 t[2] = 12

TypeError: 'tuple' object does not support item assignment

In [29]:
tuple(l)


Out[29]:
('coucou',
 'My name is {1}, {0} {1}.',
 12,
 3.14,
 ['James', 3],
 'Veuillez charger le fichier acquisition_t{:03d}.txt')

In [30]:
list(t)


Out[30]:
['coucou',
 'My name is {1}, {0} {1}.',
 127,
 3.14,
 ('James', 'Bond'),
 'Veuillez charger le fichier acquisition_t{:03d}.txt']

Librairies

Import

Toute la librairie


In [31]:
import os
os.listdir()


Out[31]:
['README.md',
 'LICENSE',
 'Initiation.ipynb',
 '.ipynb_checkpoints',
 'coucou.py',
 '.git']

Une seule fonction dans la librairie, directement accessible sans avoir à taper librairie.fonction


In [32]:
from os import listdir
listdir()


Out[32]:
['README.md',
 'LICENSE',
 'Initiation.ipynb',
 '.ipynb_checkpoints',
 'coucou.py',
 '.git']

Marche aussi avec les sous-librairies et les fonctions des sous librairies.


In [33]:
from os import path #sous-librairie de os
print(path.isfile('Initiation.ipynb'))
from os.path import isfile
print(isfile('Initiation.ipynb'))


True
True

La syntaxe maléfique de l'import de tout ce qui est dans une librairie.

from os import *

Numpy: tableaux numériques


In [34]:
import numpy as np #abbréviation du nom de la librairie pour taper 2 lettres au lieu de 5

Quelques fonctions pour créer des tableaux standards.


In [35]:
np.zeros(3), np.ones(2, complex), np.arange(4)


Out[35]:
(array([ 0.,  0.,  0.]), array([ 1.+0.j,  1.+0.j]), array([0, 1, 2, 3]))

In [50]:
l = [1,5,7] #liste numérique
print(l)
a = np.array(l) #transformée en tableau numpy
print(a)
b = np.array([1.2, 5, 6]) #les 2 étapes d'un coup
print(b)
print("a est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(a.ndim, a.shape, a.dtype)) 
print("b est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(b.ndim, b.shape, b.dtype))


[1, 5, 7]
[1 5 7]
[ 1.2  5.   6. ]
a est un tableau à 1 dimensions de taille (3,) contenant uniquement des int64
b est un tableau à 1 dimensions de taille (3,) contenant uniquement des float64

Toutes les opérations se font élément par élément, même la multiplication. Pas besoin de point comme en MATLAB. La multiplication matricielle se fait avec np.matmul.


In [51]:
print(2 * a)
print(a + b)
print(a * b)
print(a / b)
print(a>2)
print(np.exp(a))


[ 2 10 14]
[  2.2  10.   13. ]
[  1.2  25.   42. ]
[ 0.83333333  1.          1.16666667]
[False  True  True]
[    2.71828183   148.4131591   1096.63315843]

Le type des tableaux s'adapte automatiquement si besoin


In [39]:
c = a + b
print(c.dtype)
d = np.array([1,2,3])/a #division réélle, bseoin de passer en flottant, même si les tableaux ne contiennent que des entiers
print(d)
print(d.dtype)
e = np.array([1,2,3])//a #division Euclidienne, on reste en entiers
print(e)
print(e.dtype)


float64
[ 1.          0.4         0.42857143]
float64
[1 0 0]
int64

Tableaux en 2 ou plus dimensions en imbriquant des listes


In [54]:
a = np.array([[1,2,3],[7,4,5]])
print("a est un tableau à {} dimensions de taille {} contenant uniquement des {}".format(a.ndim, a.shape, a.dtype))


a est un tableau à 2 dimensions de taille (2, 3) contenant uniquement des int64

In [44]:
print(a)
print(a.T)


[[1 2 3]
 [7 4 5]]
[[1 7]
 [2 4]
 [3 5]]

De nombreuses possibilités d'indexation


In [46]:
print(a[0,1])
print(a[0])
print(a[0][1])
print(a[:,0])
print(a[::-1,[0, 2]])
print(a[a>2])


2
[1 2 3]
2
[1 7]
[[7 5]
 [1 3]]
[3 7 4 5]

Possible de faire des opération si l'un des tableaux est de dimension plus faible et si la forme de celui-ci correspond à la fin de la forme de l'autre tableau.


In [47]:
print(a)
print(b)
print(a.shape, b.shape)
a + b


[[1 2 3]
 [7 4 5]]
[ 1.2  5.   6. ]
(2, 3) (3,)
Out[47]:
array([[  2.2,   7. ,   9. ],
       [  8.2,   9. ,  11. ]])

In [48]:
a.T + b


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-48-44ff5fdd0d19> in <module>()
----> 1 a.T + b

ValueError: operands could not be broadcast together with shapes (3,2) (3,) 

In [55]:
print(a.sum())
print(a.sum(axis=0))
print(a.sum(axis=1))


22
[8 6 8]
[ 6 16]

In [ ]:

Matplotlib

Graphiques, lecture et écriture d'images

C'est sûrement la seule fois où je recommande un import *.


In [56]:
from matplotlib import pylab as plt
#permet la modification en live des figures dans le notebook
%matplotlib


Using matplotlib backend: Qt5Agg

In [57]:
plt.plot(b)


Out[57]:
[<matplotlib.lines.Line2D at 0x7fed2fed2a90>]

Pour un document à montrer, on préfère avoir des figures directement insérée dedans en tant qu'image.


In [59]:
%matplotlib inline
plt.plot(b)


Out[59]:
[<matplotlib.lines.Line2D at 0x7fed2fddc940>]

Mais on ne peut plus sélectionner les données directement, pas très pratique pour l'analyse de données. On revient donc en mode normal (fenêtre externe).


In [39]:
%matplotlib


Using matplotlib backend: Qt4Agg

In [60]:
plt.figure('Evolution de b') # création ou sélection d'une figure. La figure est nommée, ce qui est plus explicite qu'une numérotation
plt.clf() # on efface la figure courante
plt.plot(b)
plt.yscale('log')
plt.ylabel('b')
plt.xlabel(r'$\gamma_c$') # pas de caractères spéciaux, donc on a le droit de mettre des antislash pour les commandes LaTeX
plt.savefig('mafig.pdf')



In [61]:
print('a\tb')


a	b

Scipy: boîte à outil scientifique

  • traitement d'image
  • optimisation (fit)
  • fonctions spéciales
  • interpolation
  • intégration numérique