Chapitre 2
PYTHON
OU LE COUTEAU SUISSE DU DATA SCIENTIST
Mineure « Data Science » Frédéric Pennerath
Plan de travail
• Introduction à Python (débutants)
• Exercice : prétraitement des données
– Installer vos machines.
• Voir le script d’installation pour Ubuntu sur la page du cours
(www.metz.supelec.fr/metz/personnel/pennerath/Cours/DataScience)
– Créer un compte sur challengedata.ens.fr
– Etudier les compétitions.
– Former des trinômes, choisir un challenge et s’y inscrire.
– Télécharger les données de la compétition
– Commencer à explorer / mettre en forme / visualiser avec Pandas
• A faire pour la prochaine fois :
– Regarder les tutoriels Numpy et Pandas référencés sur la page du cours:
Mineure « Data Science » Frédéric Pennerath
PROGRAMMATION
Mineure « Data Science » Frédéric Pennerath
Le langage Python
Python 2 (2000) et Python 3 (2008)
– Dans la lignée de Perl :
• Langage « script » : interprété, compilé à la volée en bytecode (fichiers .ypc)
• Faiblement typé (typage à l’exécution)
• Ramasse miette
• Types de base, listes, dictionnaires
• Programmation fonctionnelle (faible)
• Programmation orientée objet (faiblement typée)
• Introspection
– Apports par rapport à Perl :
• Syntaxe plus propre et très intuitive
• Grande richesse des bibliothèques
– Forces et faiblesses :
• Les plus : flexibilité, simplicité et rapidité de développement
• Les moins : relativement lent et gourmand en mémoire, peu robuste (plantage
à l’exécution)
Mineure « Data Science » Frédéric Pennerath
Les interpréteurs Python
python : interpréteur de base Python (2.7 ou 3)
>> python3 interpréteur en ligne
>> python3 script.py exécution d’un script
(compilation en ligne)
IPython : interpréteur amélioré (2.7, ou 3)
>> ipython3
>> ipython3 script.py
>> ipython3 --matplotlib pour des affichages de courbes
Jupyter: feuilles de calcul intégrées dans une page html
>> jupyter notebook & (jadis ipython3 notebook)
Mineure « Data Science » Frédéric Pennerath
Implémentation Python :
objet, type et adresse
type(1) # builtins.int
isinstance(1, int) # True
type(True) # builtins.bool
Toute valeur est un objet ayant un type type(1.) # builtins.float
Type de v : type(v) type(1+1j) # builtins.complex
Tout objet d’un type T est dit instance de T. type("1") # builtins.str
type([ 1, 2]) # builtins.list
type(( 1, 2)) # builtins.tuple
type({ 1, 2}) # builtins.set
type({"1" : 1, 2 : "2" }) # builtins.dict
Tout objet occupe une zone mémoire définie
par sa taille et son adresse.
Adresse de v : id(v) id(1) # 10105824
Les valeurs usuelles (0, …, 256, True, False) sont id(1) # 10105824
stockées au démarrage dans des objets id(3.14) # 140004852491320
immuables. id(3.14) # 140004852491344
Les autres valeurs sont stockées dans des objets
créés dynamiquement.
Mineure « Data Science » Frédéric Pennerath
Implémentation Python :
variable et immuabilité
Les variables Python stockent l’adresse de a = [] ; id(a) # 140004852430088
l’objet, pas l’objet lui-même. b = a ; id(b) # 140004852430088
Un objet dont le type est muable est modifiable.
Une modification sur une variable dont l’objet est
a = [] ; id(a) # 140004852430088
muable ne change pas l’adresse contenue dans la
b = a ; id(b) # 140004852430088
variable mais modifie le contenu de la mémoire
b.append(1) ; a # [1]
représentant l’objet pointé.
id(b) # 140004852430088
Attention aux effets de bord !
Exemples : list, set, dict
id(1) # 10105824
id(2) # 10105856
Un objet dont le type est immuable n’est pas
a = 1 ;b = a
modifiable. Une modification appliquée à une
id(a) # 10105824
variable dont l’objet est immuable modifie l’adresse
id(b) # 10105824
contenue dans la variable, qui pointe maintenant sur
a += 1
un nouvel objet égal à l’objet modifié.
id(a) # 10105856
Exemples : int, bool, float, complex, str, tuple
id(b) # 10105824
Mineure « Data Science » Frédéric Pennerath
Implémentation Python :
méthodes et attributs
Un objet a des méthodes et des
attributs caractéristiques de son type.
Les méthodes et attributs sont les
membres d’un objet.
Un attribut a d’un objet o est une variable 1j. imag # 1.0
rattachée à o selon la syntaxe o.a
complex.conjugate(1j) # -1j
Une méthode d’un objet o est une
1j. conjugate() # -1j
fonction T.f(...) rattachée à son type T qui
prend o comme premier argument.
a = []
Une méthode T.f(o,…) peut être appelée
list.append(a,1) # [1]
selon la syntaxe o.f(…)
a.append(2) # [1,2]
L1 = [1]; L2 = [2]
Certaines méthodes définissent des L = L1 + L2
opérateurs L = L1.__add__(L2)
L = list.__add__(L1,L2)
Mineure « Data Science » Frédéric Pennerath
Implémentation Python :
classe d’objets
Une classe est un type muable défini par
l’utilisateur avec ses méthodes et ses attributs.
class Complexe:
def __init__(self, r, i = 0): self désigne l’objet courant. self.reel et
La méthode __init__ est le self.imag sont ses attributs.
self.reel = r
constructeur appelé lors
self.imag = i
de la création d’un objet de
def conjugue(self):
la classe. Il définit les
self.imag = -self.imag
attributs de l’objet
def __str__(self):
La méthode __str__ est return str(self.reel) + " + " + str(self.imag) + "i"
appelée pour convertir def __eq__(self, c):
l’objet en une chaîne de if(not isinstance(c, Complexe)):
caractères. return False
return (self.reel == c.reel)
La méthode __eq__ est and (self.imag == c.imag)
appelée lorsque l’objet sert
d’opérande gauche à c = Complexe(1,2) # Appel du constructeur
l’opérateur == de print(c) # 1 + 2i
comparaison. c.conjugue()
Mineure « Data Science » Frédéric Pennerath c == Complexe(1,-2) # True
Inspection et manipulation des valeurs
help(v) / help(t) : renvoie la liste des opérations du type de v ou du type t
>> help(1)
dir(v) / dir(t) : liste les attributs d’une valeur ou d’un type
>> dir(int)
sys.getsizeof(v) : renvoie le nombre d’octets mémoire occupés par la valeur v
>> sys.getsizeof(1) → 24
Complétion sous IPython
>> 10.(tab) →
10.bit_length 10.denominator 10.numerator
10.conjugate 10.imag 10.real
<nom T de type>(v) : convertit la valeur v en une valeur de type T (si cela a un sens)
>> float("-3.14"’) → -3.14
>> str(3.14) → ’-3.14’
print(v) : affiche la valeur v
Mineure « Data Science » Frédéric Pennerath
Opérations de base
Opérations numériques (int, long, float, complex) :
24 −1
– Calcul de mod ,3 : >> ((2 ** 4 – 1) / 2) % 3 →1
2
1+𝑗
– Calcul de Im : >> ((1+1j) /(1+1j).conjugate()).imag → 1.0
1+𝑗
– Module math : >> import math; dir(math)
Comparaisons (tout type) : ==, !=, <, >, <=, >=, cmp(x,y)
>> cmp("abc","baa") → -1
Mise à jour de variables : =,+=, -=, *=, …
Opérations et fonctions sur les chaînes :
>> infinitif = "programmer"; langage = "python".title()
>> forme = "je " + infinitif .strip("er" ) + "e en " + langage
>> mots = forme.split()
>> "-".join(mots)
>> len(forme); forme.index("en"); forme.replace("Python", "Perl")
Mineure « Data Science » Frédéric Pennerath
Les structures de contrôle
Les blocs d’instruction sont définis par indentation.
Remarques:
• Un bloc indenté ne peut être introduit qu’à la suite de « : » (if, while, def, etc)
• Faites attention à indenter un bloc de façon homogène (même nbr. de tab/espace)
Tests : Boucles :
if condition1 : for x in range(min,max+1, step) :
… …
elif condition2 :
… while condition :
else: …
… break # Sort de la boucle
continue # Passe à l’itération suivante
Exceptions :
while not(fini()):
try : pass # Boucle vide
…
raise Exception("erreur !")
except Exception as e :
print("Error: {}"..format(e))
raise # Si on veut relancer l’exception
Mineure « Data Science » Frédéric Pennerath
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour
chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène
Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en arguments de la ligne de commande.
Mineure « Data Science » Frédéric Pennerath
Les listes et les tuples
• Les listes (list) et tuples (tuple) sont des séquences non typées :
L = [1, "a"]; T = (True, L)
• Les listes sont en réalité des tableaux dynamiques (equiv. aux vecteurs de la STL)
• Les listes sont mutables, les tuples non.
• Les tuples servent souvent à renvoyer des résultats multiples depuis une fonction.
>> (a,b) = (1,2) → a = 1; b = 2
>> L = [1, 2, "a", [ 1.], False]
>> type(L) → list
>> L[0] →1
>> L[-1] → False
>> L[2:4] → ['a', [1.0]]
>> L.pop() → False
>> L.pop(0) →1
>> L.append(False) → [2, 'a', [ 1.], True]
>> sorted(L) → [True, 2, [1.0], 'a']
>> L = list(range(2,5)) → [2, 3, 4]
>> [x*2 for x in L] → [4, 6, 8]
>> [x*2 for x in L if x % 2 == 0] → [4, 8]
Mineure « Data Science » Frédéric Pennerath
Les dictionnaires
Les dictionnaires (dict) sont des tableaux associatifs (tables de hachage) non typés:
>> D={"a":1, 3: True}
>> D → {3: True, 'a': 1}
>> D["a"] →1
>> D["b"] = 2 → {3: True, 'a': 1, 'b': 2}
>> D.keys() → ['a', 3, 'b']
>> D.values() → [1, True, 2]
>> D.pop(3) → True
>> try:
entry = dictionary[word]
except KeyError:
raise Exception("Unknown word " + word)
Les ensembles (set) sont des dictionnaires sans valeurs :
>> S={"a", 3}
Les dictionnaires et listes peuvent s’imbriquer (création facilitée de graphes, etc) :
>> FdD = {"nom": "fouille de données", "vol" : 24}
>> SIR = {"nom": "SIR", "mineures" : [ FdD, …]}
>> FdD[’majeure’] = SIR
>> SIR['mineures'][0]['majeure'] == SIR → True
Mineure « Data Science » Frédéric Pennerath
Les fonctions
Déclaration de fonction :
def phrase(mots, p = '.', s = ' '):
’’’Construit une phrase a partir de mots’’’
Liste d’arguments variable :
mots[0] = mots[0].title()
def test(*positionnels, **mots_cles):
res = s.join(mots)
print("positionnels = " + str(positionnels)
res += p
print("mots clés = " + str(mots_cles)
return res
Appel de fonction : >> test(1,True, "a", a = 1, b = "b")
>> mots = ["ceci", "est", "un", "test"] positionnels = (1, True, 'a')
>> phrase(mots) → ‘Ceci est un test.' mots clés = {'a': 1, 'b': 'b'}
>> phrase(mots,’;’,’-’) → 'Ceci-est-un-test;‘
>> phrase(mots, s=’-’) → 'Ceci-est-un-test.'
Mineure « Data Science » Frédéric Pennerath
Les scripts
• Fichier texte avec extension .py
• Exécution en ligne de commande : python script.py arg1 arg2 …
import sys
def phrase(mots, p = '.', s = ' '):
"""Creer une phrase a partir de mots
"""
mots[0] = mots[0].title()
res = s.join(mots)
res += p
return res
# Ici commence le code du main :
args = sys.argv # Arguments passés en ligne de commande
args.pop(0) # Elimine le nom du script
print(phrase(args))
Mineure « Data Science » Frédéric Pennerath
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour
chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène
Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en arguments de la ligne de commande.
Mineure « Data Science » Frédéric Pennerath
Programmation fonctionnelle et fonctions lambda
Le type fonction
Les fonctions sont des valeurs dont les noms sont des variables :
>> def carre(x): return x*x
>> f = carre; f(2) →4
>> carre = 1; carre(2) → TypeError: 'int' object is not callable
>> def map2(f, L):
return [f(x) for x in L]
>> map2(carre, range(1,5)) → [1, 4, 9, 16]
Fonctions lambda et paramétrisation d’algorithmes :
>> map(lambda x : x*x, range(1,5)); filter(lambda x : x%2 == 0, range(1,5))
>> L=[{"n" : 1, "m" : 3}, {"n" : 3, "m" : 2}, {"n" : 2, "m" : 1}]
>> sorted(L, key = lambda x: x["m"], cmp = lambda x,y: cmp(y,x))
→ [{'m': 3, 'n': 1}, {'m': 2, 'n': 3}, {'m': 1, 'n': 2}]
Mineure « Data Science » Frédéric Pennerath
Les itérables et les boucles
Itérable : object renvoyant un itérateur utilisé par les boucles for
>> for x in <iterable> : print(x)
Exemples d’énumérations:
D’une liste : >> for x in [1,2,3]: ...
D’un tuple : >> for x in (1,2,3): ...
D’une chaîne : >> for x in "abcd":
D’un ensemble : >> for x in {1,2,3}:
Des clés d’un dictionnaire : >> for x in {"a" : 1, "b" : 2, "c" : 3}:
Des valeurs d’un dictionnaire : >> for x in {"a" : 1, "b" : 2, "c" : 3}.values():
Des lignes d’un fichier texte >> for x in open(file= "fichier", mode = "r")
Listes par compréhension
>> [x ** 3 for x in range(1,10) ] // Equivalent à map
>> [x for x in range(1,10) if (x % 2 == 0) ] // Equivalent à filter
>> [x ** 3 for x in range(1,10) if (x % 2 == 0) ] // Map + Filter
>> [(i,j) for i in range(1,5) for j in range(1,i+1)] // double itération
>> [(i,j) for i in range(1,5) if(i % 2 == 0) for j in range(1,i+1)]
Mineure « Data Science » Frédéric Pennerath
Les fichiers
Accès en lecture:
>> f = open(file=fileName, mode="r", encoding="utf-8", errors='replace')
>> for line in f:
>> ...
>> f.close()
Accès en écriture :
>> f = open(file=fileName, mode="w", encoding="utf-8")
>> print("passage à la ligne suivante", file = f)
>> print("sans saut de ligne", file = f, end = '')
>> f.close()
Enumérer les fichiers d’un répertoire :
>> from os import listdir
>> for fileName in listdir("."): print(filename)
Mineure « Data Science » Frédéric Pennerath
L’écriture formatée de fichiers et
les chaînes de formatage
Simple substitution :
>> S = "{} : capitale = {2}, surface = {1} m2"
>> S.format(’France’,674843, ’Paris’)
→ ’France : capitale = Paris, surface = 674843 m2’
Justification au centre à gauche et à droite:
>> S = "{:^10} : capitale = {:.<10}, surface = {:>10} m2"
>> S.format(’France’, ’Paris’, 674843)
→ ' France : capitale = Paris....., surface = 674843 m2'
Formattage des nombres
>> "{:.2f}".format(3.1415) → '3.14'
>> "{:.2e}".format(3.1415) → '3.14e+00'
>> "{:.1%}".format(0.1531) → '15.3%'
Mineure « Data Science » Frédéric Pennerath
L’analyse de fichiers et
les expressions régulières
Expression régulière :
Décrit un ensemble des chaînes de caractères reconnues par un automate
Langage des expressions régulières :
langage de spécification d’un automate
Exemple : \d+ succession de chiffres de 0 à 9
Utile pour analyser le contenu de fichiers textes
Compilation génération de l’automate
>> import re
>> S = "T = -40, P = 100, V = 2.1"
>> expr = re.compile(’\d+’)
>> expr.findall(S)
→ ['40', '100', '2', '1']
>> expr = re.compile('-?\d+\.?\d+') ; expr.findall(S)
→ ['-40', '100', '2.1']
>> expr.split(S)
→ ['T = ', ', P = ', ', V = ', '']
>> expr = re.compile('(\w+)\s*=\s*(-?\d+\.?\d+)') ; expr.findall(S)
→ [('T', '-40'), ('P', '100'), ('V', '2.1')]
Mineure « Data Science » Frédéric Pennerath
Les expressions régulières
Expression Correspondance
. Tout caractère
[x-y] Tout caractère entre x et y inclus
\w, \d, \s Tout caractère alphanumérique, tout chiffre, tout espace
\W, \D, \S Négations de \w, \d, \s
exp* Occurrences de exp de 0 ou plusieurs fois
exp+ Occurrences de exp au moins une fois
exp? Occurrences de exp au plus 1 fois
exp{n,m} Occurrences de exp de n à m fois
(exp) Fait correspondre exp à une variable $n
exp1|exp2 Alternative entre exp1 et exp2
^,$ Correspond au début et à la fin de la chaîne
\x Caractère x, si x est un caractère spécial (.,*,\,+,?,|,…)
Mineure « Data Science » Frédéric Pennerath
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour
chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène
Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en argument de la ligne de commande.
Mineure « Data Science » Frédéric Pennerath
La programmation objet
class Poly:
Fichier « Poly.py »
'un polynome a coefs reels'
# Constructeur
def __init__(self, C=[]):
self.coefs = C
# Conversion str(self)
def __str__(self):
L = [ "{:2.2f} X^{}".format(self.coefs[i],i)
for i in range(len(self.coefs)) ]
L.reverse()
return "+".join(L)
# Opération self + P
def __add__(self, P):
L = [ (x + y) for (x,y) in zip(self.coefs, P.coefs) ]
L += self.coefs[len(P.coefs):]
L += P.coefs[len(self.coefs):]
return Poly(L)
# Attributs statiques
Poly.X = Poly([0, 1]) # Monôme X
Poly.I = Poly([1]) # Constante 1
from Poly import Poly
P = Poly([0, 1])
print(P + Poly.X)
Mineure « Data Science » Frédéric Pennerath
Les itérateurs
Itérateur : permet l’énumération d’éléments (pas forcément de structures de
données sous-jacentes)
Exemple : range(min, max, step)
>> L = list(range(1,10000))
>> sys.getsizeof(L) → 80056
>> G = range(1,10000)
>> sys.getsizeof(G) → 32 !!!
Itérateurs paresseux versus liste par compréhension
>> L2 = [ 2*x for x in G ]
>> sys.getsizeof(L2) → 87624
>> G2 = ( 2*x for x in G )
>> sys.getsizeof(G2) → 72 !!!
Exemple d’application : transformation d’un fichier en Θ(1)
>> f = open(fileName, 'r')
>> g = ( l.upper() for l in f )
>> for l in g: print(l)
Mineure « Data Science » Frédéric Pennerath
Itérateurs et itérables « faits maison »
class Poly:
...
# Itérable : retourne un itérateur
def __iter__(self): return Iter(self.coefs)
class Iter:
# Constructeur de l'itérateur
def __init__(self, coefs):
self.it = iter(coefs) # Itérateur de la liste de coefs.
self.degre = -1
# next renvoie le prochain élément ou exception StopIteration
def __next__(self):
while(True):
coef = next(self.it) # Peut produite une StopIteration
self.degre += 1
if(coef != 0.): return(coef, self.degre)
# Un itérateur est un itérable
def __iter__(self): return self
Mineure « Data Science » Frédéric Pennerath
Les générateurs
class Poly:
...
# Renvoie un générateur
def getCoefs(self):
degre = 0
for c in self.coefs:
if(c != 0.):
# yield renvoie une valeur
yield (degre, c)
degre += 1
…
for c in P.getCoefs():
print(c)
Mineure « Data Science » Frédéric Pennerath