Vous êtes sur la page 1sur 113

Premiers Pas

avec Python 3
Pourquoi un langage interprété ?
• Des besoins classiques:
• Mettre au point rapidement une Proof of Concept d’un algorithme
• Automatiser une tâche de pré ou post-processing de données
• Changement de priorité : faire avant d’optimiser

• Des écueils classiques


• Langages compilés : cycle de écriture/compilation trop long
• Langages dédiés: problématique de la multiplication des outils

• Utilisons donc un langage de script: PYTHON 3 2


Pourquoi un langage interprété ?

• Plutôt que BASH/AWK/PERL ?


• Niveau d’abstraction plus élevé
• Bibliothèque d’outils annexes très fournies
• Communauté très large

• Plutôt que C/C++ ?


• Cycle de développement plus court
• Simplification de tâches courantes
• Simplification de la gestion des ressources 3
Objectifs de la formation
• Prises en main de l’environnement
• Interpréteur en ligne de commande
• Notion de bases du langages

• Eléments fondamentaux de programmation PYTHON


• Fonctions, structures de données
• Aspect objet

• Outillage annexe
4
Programmer avec
Python 3
Prise en main de l’interpréteur
• Lancement en mode interactif

$ python3.7
Python 3.7 (default, Sep 16 2015, 09:25:04)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

• Eléments de base
• Prompt primaire: >>>
• Prompt secondaire (ligne de continuation) : ...
• Commentaires débutant par # 6
Prise en main de l’interpréteur
• Exercice 1 – Python & les nombres :
• Reproduisez les commandes suivantes dans votre interpréteur
>>> 2 + 2 # 2 est un nombre entier de type int
4
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5 # la division s’évalue toujours comme un nombre réel
1.6
>>> 17 // 5 # la division entière est utilisable via l’opérateur //
3
>>> 17 % 5 # le modulo est utilisable via l’opérateur %
2
>>> 2 ** 75 # ** est l’opérateur puissance 7
37778931862957161709568
Prise en main de l’interpréteur
• Exercice 2 – Python & les variables:
• Reproduisez les commandes suivantes dans votre interpréteur

>>> width = 20
>>> height = 5 * 9
>>> width * height
900
>>> edge = 1.9 # edge est un nombre réel de type float
>>> edge ** 2 # calcul de edge à la puissance 2
3.61
>>> _ + width*height # _ est le dernier résultat calculé dans le shell
903.61
8
Prise en main de l’interpréteur
• Exercice 3 – Autres types Python – Chaine de caractères :
• Reproduisez les commandes suivantes dans votre interpréteur

>>> 'spam eggs' # simple quotes


'spam eggs'
>>> 'doesn\'t' # utilisez \’ pour insérer le caractére '
"doesn't"
>>> "doesn't" # ... ou utilisez des guillemets
"doesn’t"
>>> print("du texte en UTF8 🤖👾😸 ") # Primitive d’affichage
du texte en UTF8 🤖👾😸 ...

9
Structures de contrôles
• Principes:
• Modifient le flot d’exécution du programme
• Notion de répétitions
• Notion d’exécution conditionnelles
• Utilisables directement en mode interactif

• Mots-clés disponibles
• if
• for
• while
10
Structures de contrôles – if

>>> x = int(input("Entrez une valeur entière: "))


Entrez une valeur entière: 42
>>> if x < 0:
... x = 0
... print(‘Valeur negative')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print(‘Unique')
... else:
... print(‘Plusieurs')
...
Plusieurs

11
Structures de contrôles – if

>>> x = int(input("Entrez une valeur entiere: "))


Entrez une valeur entiere: 42
>>> if x < 0:
... x = 0
... print(‘Valeur negative')
... elif x == 0:
... print('Zero') elif
... elif x == 1:
... print(‘Unique')
... else:
... print(‘Plusieurs')
...
Plusieurs

12
Structures de contrôles – if

>>> x = int(input("Entrez une valeur entiere: "))


Entrez une valeur entiere: 42
>>> if x < 0:
... x = 0
... print(‘Valeur negative')
... elif x == 0:
... print('Zero') else
... elif x == 1:
... print(‘Unique')
... else:
... print(‘Plusieurs')
...
Plusieurs

13
Structures de contrôles – while

>>> # La suite de Fibonacci:


... # la somme de deux valeurs définie le suivant
... a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8

14
Structures de contrôles – while

>>> # La suite de Fibonacci:


... # la somme de deux valeurs définie le suivant
... a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8

15
Structures de contrôles – while

>>> # La suite de Fibonacci:


... # la somme de deux valeurs définie le suivant
... a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8

16
Structures de contrôles - for
• Principe:
• Itération sur les éléments d’une séquence de manière immutable
• Notation spécifique pour les boucles mutables

>>> # Mesure de la longueur de mots:


>>> words = ['chat', 'chien', 'poisson']
>>> for w in words:
... print(w, len(w))
...
chat 4
chien 5
poisson 7

17
Structures de contrôles - for
• Principe:
• Itération sur les éléments d’une séquence de manière immutable
• Notation spécifique pour les boucles mutables

>>> # Mesure de la longueur de mots:


>>> words = ['chat', 'chien', 'poisson']
>>> for w in words[:]:
... words.append(w)
... print(words)
['chat', 'chien', 'poisson', 'chat', 'chien', 'poisson']

18
Structures de contrôles - for
• Itération par index numérique:

>>> for i in range(5):


... print(i)
...
0
1
2
3
4

19
Structures de contrôles – Sortie anticipée
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(n, ‘ est égal a', x, '*', n//x)
... break
... else:
... # La boucle for arrive ici si pas de sortie anticipée
... print(n, ‘est premier')
...
2 est premier
3 est premier
4 est égal a 2 * 2
5 est premier
6 est égal a 2 * 3
7 est premier
8 est égal a 2 * 4
9 est égal a 3 * 3
20
Structures de contrôles – Instruction nilpotente

>>> for n in range(1, 10):


... if n % 2 == 0:
... pass
... else:
... print(n, ‘ est pair')
...
2 est pair
4 est pair
6 est pair
8 est pair

21
Structures de contrôles – Instruction nilpotente

>>> for n in range(1, 10):


... if n % 2 == 0:
... pass
... else
... print(n, ' est pair', x, '*', n//x)
...
2 est pair
4 est pair
6 est pair
8 est pair

22
Aspect Impératif
Principes généraux

>>> def fib(n):


... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Appel de la function
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

24
Principes généraux

>>> def fib(n):


... a, b = 0, 1 def:
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Appel de la function
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

25
Principes généraux

>>> def fib(n):


... a, b = 0, 1 :
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Appel de la function
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

26
Principes généraux
>>> fib(200)
0 1 1 2 3 5 8 13 21 34 55 89 144
• Retour des fonctions: >>> print(fib(200))
None
• Par défaut, les fonctions
sans valeur de retour
renvoient la valeur None >>> def fib(n):
... a, b = 0, 1
• Le mot-clé return permet ... l = []
de spécifier la valeur ... while a < n:
... l.append(a)
renvoyée par la fonction
... a, b = b, a+b
... return l
...
>>> print(fib(200))
[0 1 1 2 3 5 8 13 21 34 55 89 144]
27
Fonctions et Arguments
• Arguments par défauts >>> def fib(n=10):
• Il est possible de spécifier la ... a, b = 0, 1
... l = []
valeur par défaut d’un ou
... while a < n:
plusieurs arguments dans la ... l.append(a)
définition de la fonction ... a, b = b, a+b
... return l
• Les arguments par défaut se ...
positionnent nécessairement >>> print(fib())
[0 1 1 2 3 5 8]
en fin de la liste des
arguments

28
Fonctions et Arguments
• Arguments nommés
• Il est possible de spécifier un nom pour un argument lors d’un appel de fonction
• La valeur de ces arguments est alors passée soit traditionnellement soit en utilisant le
nom de l’argument
• Les arguments nommés se placent après les arguments classiques

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):


print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

29
Fonctions et Arguments
• Arguments nommés
• Il est possible de spécifier un nom pour un argument
• La valeur de ces arguments est alors passé soit traditionnellement soit en utilisant le nom
de l’argument
• Les arguments nommés se placent après les arguments classiques

parrot(1000) # 1 argument positionnel


parrot(voltage=1000) # 1 argument nommé
parrot(voltage=1000000, action='VOOOOOM') # 2 arguments nommés
parrot(action='VOOOOOM', voltage=1000000) # 2 arguments nommés
parrot('a million', 'bereft of life', 'jump') # 3 arguments positionnels
parrot('a thousand', state='pushing up the daisies') # 1 positionnel, 1 nommé

30
Fonctions et Arguments
• Arguments nommés
• Il est possible de spécifier un nom pour un argument
• La valeur de ces arguments est alors passé soit traditionnellement soit en utilisant le nom
de l’argument
• Les arguments nommés se placent après les arguments classiques

parrot() # Incorrect: argument manquant


parrot(voltage=1000000, ‘dead’) # Incorrect: 2 arguments nommés
parrot(110, voltage=220) # Incorrect: argument dupliqué
parrot(color=‘Red’) # Incorrect: argument inconnu

31
Fonctions et Arguments
• Arguments dictionnaires
• Une liste arbitraires d’arguments nommés peuvent être récupérée dans un dictionnaire
• La notation **name introduit un tel dictionnaire
• Le contenu du dictionnaire est ensuite utilisable depuis la fonction

def list_of(kind, **keywords):


print('This is a list of ', kind)
for kw in keywords:
print(kw, ":", keywords[kw])

>>> list_of('string', name=‘George', town='London’)


This is a list of string
name : George
town : London 32
Fonctions et Arguments
• Arguments arbitraires
• Une liste arbitraires d’arguments peuvent être récupérer dans un tuple
• La notation *name introduit un tel tuple
• Le contenu du tuple est ensuite utilisable de puis la fonction
• Utilisable en combinaison avec **args

def list_of(kind, *keywords):


print('This is a list of ', kind)
for kw in keywords:
print(“> ", kw)

>>> list_of('string', ‘George', 'London’)


This is a list of string
> George
> London 33
Fonctions et Arguments
• Séparation d’arguments
• Une fonction attend N arguments
• Les valeurs que l’on désire passer à cette fonction sont contenues dans une collection
• Syntaxe permettant de séparer la collection en autant d’argument que nécessaire

>>> list(range(3, 6)) # Appel direct avec arguments classiques


[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # Appel avec arguments éclatés depuis une liste
[3, 4, 5]

34
Fonctions anonymes
• Principes
• Fonction courte (une expression) utilisable localement sans définition
• Argument classique des fonctions attendant elles-mêmes une fonction en paramètre:
On parle de fonction d’ordre supérieure
• Introduite par le mot clé lambda

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

35
Générateurs
• Principes
• Fonction avec un état dont def G():
n = 1
l’évolution dans le temps est print('Etape 1')
segmentée yield n

• Un générateur renvoie une ou n += 1


plusieurs valeurs via le mot clé print('Etape 2')
yield n
yield
• Le générateur est évalué pas à n += 1
print('Fin de G')
pas via l’instruction next yield n
• Le générateur est utilisable
directement dans une boucle
for 36
Générateurs
• Principes
• Fonction avec un état dont >>> a = G()
>>> next(a)
l’évolution dans le temps est Etape 1
segmentée 1
>>> next(a)
• Un générateur renvoie une ou Etape 2
plusieurs valeurs via le mot clé 2
>>> next(a)
yield
Fin de G
• Le générateur est évalué pas à 3
pas via l’instruction next >>> for item in my_gen():
... print(item)
• Le générateur est utilisable
directement dans une boucle
for 37
Exercices – Fonctions
• Saut aléatoire
On imagine une puce qui se déplace aléatoirement sur une ligne, en avant ou en arrière, par pas de
1 ou -1. Par exemple, si elle est à l'emplacement 0, elle peut sauter à l'emplacement 1 ou -1; si elle
est à l'emplacement 2, elle peut sauter à l'emplacement 3 ou 1, etc.

Avec une boucle while, simuler le mouvement de cette puce de l'emplacement initial 0 à
l'emplacement final 5. Combien de sauts sont nécessaires pour réaliser ce parcours ? Relancez
plusieurs fois le programme. Trouvez-vous le même nombre de sauts à chaque exécution ?
Vous utiliserez l'instruction random.choice([-1,1]) qui renvoie au hasard les valeurs -1 ou 1 avec
la même probabilité. Avant d'utiliser cette instruction vous mettrez au tout début de votre script la
ligne: import random

38
Exercices – Fonctions
• La conjecture de Syracuse
• La conjecture de Syracuse est une conjecture mathématique qui reste improuvée à ce jour et qui
est définie de la manière suivante :
Soit un entier positif n. Si n est pair, alors le diviser par 2. Si il est impair, alors le multiplier par
3 et lui ajouter 1. En répétant cette procédure, la suite de nombres atteint la valeur 1
puis se prolonge indéfiniment par une suite de trois valeurs triviales appelée cycle trivial.
Jusqu'à présent, la conjecture de Syracuse, selon laquelle depuis n'importe quel entier positif la
suite de Syracuse atteint 1, n'a pas été mise en défaut. Par exemple, les premiers éléments de la
suite de Syracuse si on prend comme point de départ 10 sont : 10, 5, 16, 8, 4, 2, 1...

Créez un script qui, partant d'un entier positif n (par exemple 10 ou 20), crée une liste des nombres
de la suite de Syracuse. Avec différents points de départ, la conjecture de Syracuse est-elle
toujours vérifiée ? Quels sont les nombres qui constituent le cycle trivial ?
39
Structures de
Données
Liste
• Type composite contenant plusieurs valeurs de types arbitraires
• Syntaxe de base:
L = [1, 2, 3, 4]

• Propriétés:
• Les listes sont ordonnées
• Les éléments d’une liste sont accessibles via un index
• Les listes sont emboitables (liste de liste de …)
• Les listes sont mutables
• Les listes ont un contenu et une taille dynamique
41
Liste
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
>>> squares[0]
1
>>> squares[-1]
25
>>> squares[-3:]
[9, 16, 25]
>>> squares[:] # Copie effective de squares
[1, 4, 9, 16, 25]
>>> squares + [36, 49, 64, 81, 100] # Concatenation
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> squares[1:3] = [2] # Remplacement partiel
[1, 2, 16, 25]

42
Liste

• Opérations sur les listes


• len(l) : Calcule la longueur de la liste
• l.append(x) : Ajoute un élément à la fin de la liste
• l.extend(iterable) : Ajoute un ensemble de valeur à la fin de la liste
• l.insert(i, x) : Insert une valeur à un index donné
• l.remove(x) : Retire l’élément x de la liste
• l.pop(i) : Retire l’élément à l’index i de la liste
• l.clear() : Vide la liste de son contenu

43
Liste

• Opérations sur les listes


• l.index(x[, start[, end]]): Renvoie la position du premier élément de la liste égal à x
• l.count(x): Renvoie le nombre d’éléments de la liste égaux à x
• l.sort(key=None, reverse=False): Tri les éléments de la liste (selon une clé)
• l.reverse(): Inverse l’ordre des éléments de la liste
• l.copy(): Retourne une copie superficielle de la liste (comme l[:] ou llist(l))

44
Compréhension de Liste
• Principes:
• Syntaxe compacte de génération de liste

• Se base sur une description humainement compréhensible d’une formule


• Notion de compréhension imbriquée ou filtrée

>>> squares = [x**2 for x in range(10)]


>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]


[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

45
Compréhension de Liste
• Principes:
• Syntaxe compacte de génération de liste

• Se base sur une description humainement compréhensible d’une formule


• Notion de compréhension imbriquée

>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]

>>> [[row[i] for row in matrix] for i in range(4)]


[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
46
Chaîne UNICODE
• Syntaxe de base:
• Mono-ligne : b = "Hello, World!"
• Multi-lignes: b = """ Hello, World!
From a world with multiple
lines in a single string !
"""

• Propriétés:
• Les chaîne de caractères sont des listes de caractères
• Elles sont immutables
• Elles supportent les mêmes opérations d’indexations que les listes
• Elles fournissent des opérations spécifiques
47
Chaîne UNICODE

• Quelques opérations sur les chaînes UNICODE


• len(s) : Calcule la longueur de la chaîne
• s.strip() : Retire les espaces blancs en début et fin de la chaîne
• s.lower() : Renvoie la chaîne en minuscule
• s.upper() : Renvoie la chaîne en majuscule
• s.replace(c1,c2) : Renvoie une nouvelle chaîne où les instance de c1 sont
remplacées par c2 dans la chaîne
• s.split(sep) : Renvoie la liste des sous-chaines obtenues par découpage
autour d’un séparateur

48
Tuple

• Type composite contenant plusieurs valeurs de types hétérogènes


• Syntaxe de base:
T = 1,’2’,3.5432,[1,4]

• Propriétés:
• Les tuples sont immuables
• Pas de contraintes de types pour les éléments
• Les tuples sont imbriquables
• Les éléments des tuples sont accessibles par déballages ou indexation

49
Tuple
>>> t = 12345, 54321, 'hello!'
>>> t
(12345, 54321, ‘hello!’)
>>> t[1] # Accès par indexation
54321

>>> u = t, (1,2,3,4,5) # Imbrication de tuples. Notez le parenthésage


>>> u
((12345, 54321, 'hello!’),(1, 2, 3, 4, 5))

>>> x, y, z = t # Déballage du tuple

>>> t[0] = 77 # Immuabilité


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
50
Tuple

>>> empty = () # Tuple vide


>>> singleton = 'hello', # Tuple à un seul élément. Notez la virgule terminale

>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

51
Ensemble

• Type composite contenant des valeurs ordonnées uniques


• Syntaxe de base:
S = {'Hello', 'Bonjour', 'Buenos dias'}

• Propriétés:
• Les ensembles contiennent des valeurs dont les doublons sont éliminés
• Support pour les tests d’appartenance
• Support des opérations ensemblistes classiques
• Les éléments des ensembles sont accessibles par déballages ou indexation

52
Ensemble

>>> panier = {'pomme','orange','pomme','poire','orange','banane'}


>>> print(panier) # Pas de duplicata dans le panier
{'orange', 'banane', 'poire', 'pomme’}

>>> 'orange' in panier # Test d’appartenance


True
>>> ‘myrtille’ in panier
False

53
Ensemble

>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # Lettres uniques de a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # Lettres de a mais pas de b
{'r', 'd', 'b'}
>>> a | b # Lettres de a ou de b
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # Lettres de a et de b
{'a', 'c'}
>>> a ^ b # Lettres de a ou de b mais pas des deux
{'r', 'd', 'b', 'm', 'z', 'l'}

54
Ensemble immuable

• Type composite immuable contenant des valeurs ordonnées uniques


• Syntaxe de base:
F = frozenset('a', ‘e', ‘i', ‘o', ‘u', )

• Propriétés:
• Interface identique aux ensembles classiques
• Leur immuabilité les rendent utilisables comme clés de dictionnaires

55
Dictionnaire

• Type composite contenant des paires clé/valeur


• Syntaxe de base:
D = {'mercenaire':7, 'vendredi':13, 'mousquetaire':4}

• Propriétés:
• Les dictionnaires sont des tables associatives qui associent des clés immuables à
des valeurs arbitraires
• Les valeurs sont accessibles par leurs clés respectives
• Les paires clé/valeur sont ajoutables ou retirables à volonté du dictionnaire

56
Dictionnaire
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'guido': 4127, 'irv': 4127}
>>> list(tel)
['jack', 'guido', 'irv']
>>> sorted(tel)
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
57
False
Dictionnaire

>>> tel = {'jack': 4098, 'sape': 4139}


>>> tel['guido'] = 4127

>>> print(tel.keys())
dict_keys(['jack', 'sape', 'guido’])

>>> print(tel.values())
dict_values([4098, 4139, 4127])

>>> print(tel.items())
dict_items([('jack', 4098), ('sape', 4139), ('guido', 4127)])

58
Exercices – Structures de données

• Manipulation de listes et de chaînes


• Créez une fonction hamming() qui prend comme argument deux chaînes UNICODE de
même taille et renvoi la distance de Hamming de ces deux chaînes, à savoir le nombre
de position dans la chaînes ou les deux caractères différent. Par exemple : SAXPY et
DAXPZ ont une distance de Hamming de 2.

• Créez une fonction describe() qui prend comme argument une liste d’entier et renvoi
la liste auto descriptive de cette liste. Une liste auto descriptive d’entier est obtenu en
générant la liste énumérant le nombre de chaque chiffre. Par exemple, la liste auto
descriptive de [2, 3, 3, 1, 1, 1] est [1, 2, 2, 3, 3, 1] car elle contient une fois 2 puis deux
fois 3 et trois fois 1. 59
Exercices – Structures de données
• Géométrie amusante
• Créez une fonction creer_point() qui prend comme argument 3 réels et qui renvoit un
tuple contenu ces trois valeurs. On considérera que ce tuple représente un point 3D
(x,y,z).

• Créez une fonction barycentre() qui prend comme argument une liste de tuple crées
par creer_point() et renvoi le tuple contenant le barycentre de ces points.

• Créez une fonction nearest() qui prend comme argument une liste de tuple crées par
creer_point() et un unique tuple de 3 réel et renvoi le point de la liste le plus proche
de son deuxième argument
60
Exercices – Structures de données
• Analyse ADN
• Créez une fonction compte_mots_2_lettres() qui prend comme argument une séquence sous la
forme d'une chaîne de caractères et qui renvoie tous les mots de 2 lettres qui existent dans la
séquence sous la forme d'un dictionnaire.

Par exemple pour la séquence ACCTAGCCCTA, le dictionnaire renvoyée serait :


{'AC': 1, 'CC': 3, 'CT': 2, 'TA': 2, 'AG': 1, 'GC': 1}

• Créez une nouvelle fonction compte_mots_3_lettres() qui a un comportement similaire à


compte_mots_2_lettres() mais avec des mots de 3 lettres.
• Utilisez ces fonctions pour affichez les mots de 2 et 3 lettres et leurs occurrences trouvés dans la
séquence d'ADN :
61
ACCTAGCCATGTAGAATCGCCTAGGCTTTAGCTAGCTCTAGCTAGCTG
Structurer son
programme Python
The Zen of Python
• Errors should never pass silently.
• Beautiful is better than ugly.
• Unless explicitly silenced.
• Explicit is better than implicit.
• In the face of ambiguity, refuse the temptation to guess.
• Simple is better than complex. • There should be one-- and preferably only one --obvious way
to do it.
• Complex is better than complicated.
• Although that way may not be obvious at first unless you're
• Flat is better than nested. Dutch.
• Now is better than never.
• Sparse is better than dense.
• Although never is often better than *right* now.
• Readability counts.
• If the implementation is hard to explain, it's a bad idea.
• Special cases aren't special enough to break the • If the implementation is easy to explain, it may be a good
rules. idea.

• Although practicality beats purity. • Namespaces are one honking great idea -- let's do more of
those!
63
Le style PEP8
• Principes:
• PEP8 est un ensemble de règles de « savoir-vivre » Python
• Standard de facto supporté par des outils de vérifications
• Outils de support : flake8

• Règle PEP8 (1/2) :


• Utilisez des indentations de 4 espaces et pas de tabulation.
• Faites en sorte que les lignes ne dépassent pas 79 caractères
• Utilisez des lignes vides pour séparer les fonctions et les classes, ou pour scinder de gros
blocs de code à l'intérieur de fonctions.
• Lorsque c'est possible, placez les commentaires sur leur propres lignes. 64
Le style PEP8

• Règle PEP8 (2/2) :


• Utilisez les chaînes de documentation.

• Utilisez des espaces autour des opérateurs et après les virgules, mais pas juste à l'intérieur des
parenthèses : a = f(1, 2) + g(3, 4).
• Utilisez une convention de nommage unique pour vos classes et fonctions.
• N'utilisez pas d'encodage exotique dès lors que votre code est censé être utilisé dans des
environnements internationaux.

65
Notion de Script
• Principes:
• Un script PYTHON est un ensemble d’opérations agrégées dans un fichier exécutable
• Il est préférable de fournir un en-tête pour spécifier le fait que l’on utilise PYTHON
• Exemple : monscript.py
#!/usr/bin/env python3
print('Hello World!')

• Exemple d’exécution

$bash ./monscript.py
Hello World!

66
Notion de Script
• Arguments de lignes de commandes:
#!/usr/bin/env python3

import sys

print('Nombre d’arguments :', len(sys.argv), 'arguments.’


print('Liste des arguments :', str(sys.argv)

$ ./monscript.py arg1 arg2 toto


Nombre d’arguments : 4 arguments.
Liste des arguments : ['monscript.py', 'arg1', 'arg2', ‘toto']

67
Notion de Module

• Principes:
• Un module PYTHON est un ensemble de définitions et d’opérations agrégées dans un fichier
• Ce fichier est ensuite importable par python (en mode interactif ou script) pour retrouver les
définitions ainsi agrégées
• Un module à un nom et ce nom sert de préfixe aux éléments qui y sont définis.
• PYTHON fournit aussi des modules standards qui fournissent des opérations de bases

68
Notion de Module - Définition
# Module Fibonacci : fichier fibo.py

def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()

def fib2(n):
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
69
Notion de Module – Importation et utilisation

>>> import fibo


>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>> fibo.__name__ # Nom du module


'fibo'

>>> fib = fibo.fib # Renommage local


>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

70
Notion de Module – Importation sélective
>>> from fibo import fib, fib2
>>> fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>> fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>> from fibo import *


>>> fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>> fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

71
Notion de Module – Importation avec renommage

>>> import fibo as fib


>>> fib.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>> fib.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>> from fibo import fib as fibonacci


>>> fibonacci(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

72
Notion de Module – Exécution comme script
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()

if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))

$ python3 fibo.py 50
0 1 1 2 3 5 8 13 21 34

73
Les Doc String
• Objectifs :
• Intégrer au langage le support de la documentation du logiciel.
• Récupération automatique via la fonction d’aide.
• Manipulation par des outils externes.

def square(a):
'''Renvoie le carré de l’argument a.'''
return a**a

# Plus tard
>>> help(square)
Help on function square in module __main__:

square(a)
Renvoie le carré de l’argument a.
74
Les Doc String
def square(a):

return a**a

# Plus tard
>>> help(square)
square(a)
Fonction de calcul du carré

Parameters: argument1 (int): Valeur à mettre au carré

Returns: int:Carré de l’argument


75
Tests unitaires
• Module doctest
• Intégrer au langage le support de tests unitaires.
• Basé sur un principe similaire aux doc strings
• Un test = un appel interactif + son résultat attendu sous forme de chaîne de caractères

def average(values):
"""Computes the arithmetic mean of a list of numbers.

>>> print(average([20, 30, 70]))


40.0
"""
return sum(values) / len(values)

import doctest
doctest.testmod() # Validation des tests inclus dans la docstring 76
Tests unitaires
def average(values):
"""Computes the arithmetic mean of a list of numbers.

>>> print(average([20, 30, 70]))


40.0
"""
return sum(values) / len(values) + 1

**********************************************************************
File "main.py", line 4, in __main__.average
Failed example:
print(average([20, 30, 70]))
Expected:
40.0
Got:
41.0
**********************************************************************
1 items had failures:
1 of 1 in __main__.average
***Test Failed*** 1 failures.
77
Benchmarks
• Module timeit
• Effectue une mesure statistique du temps d’exécution d’un fragment de code PYTHON

• Prise en charge des réplications nécessaires à la qualité de la mesure

>>> import timeit


>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001

>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)


0.2727368790656328

>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)


0.23702679807320237

78
Aspect Orienté Objet
Notion de classe
• Principes généraux
• Une classe = données + fonctionnalités

• Créer une nouvelle classe crée un nouveau type d'objet prêt à l’emploi
• Les classes Python se veulent plus souples et dynamiques que leur équivalent C++ ou JAVA

• Le modèle Objet en PYTHON


• Attribut donnée et méthode
• Héritage simple et multiple
• Notion de record

80
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""

Le mot-clé class introduit la définition


d’un objet classe. Cette objet contient
un ensemble de définitions ou d’opérations
qui sont exécutées pour construire les
éléments de la classe.

81
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""

Tout comme les fonctions, les objets


classe peuvent contenir un docstring.

82
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""

def real(self):
return self.r Les fonctions membres se
définissent comme des fonctions
dans le « scope » de la classe.
def imag(self):
return self.i

83
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""

def real(self):
return self.r self représente l’objet courant
sur lequel la fonction membre va
s’exécuter.
def imag(self):
return self.i

84
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""
Les données membres sont
def real(self): définies à la volée lorsque
return self.r le besoin s’en fait sentir.

Contrairement à d’autres
def imag(self): langages, elles ne sont pas
return self.i « prédéfinies »

85
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""
La passage de la définition d’un
def real(self): objet classe à une instance de la
classe se fait par l’appel d’un
return self.r
constructeur introduit par une
fonction __init__
def imag(self):
return self.i

def __init__(self, realpart, imagpart):


self.r = realpart
self.i = imagpart

86
Classe - Définition

class MyComplex:
"""Une classe de nombre complexe"""

def real(self):
return self.r

def imag(self): On peut définir des membres de


return self.i classes, partagés par toutes les
instances en définissant une
def __init__(self, realpart, imagpart): variable au sein de la classe
self.r = realpart
self.i = imagpart

is_complex = True
87
Classe - Utilisation

x = MyComplex(3,2)

print(x.real() , " + i" , x.imag())

L’instanciation de la classe passe par l’appel


au constructeur

88
Classe - Utilisation

x = MyComplex(3,2)

print(x.real() , " + i" , x.imag())

Une fois instancié, l’objet peut utiliser ses


fonctions membres

89
Classe - Utilisation

x = MyComplex(3,2)

print(x.real() , " + i" , x.imag())

x.is_imag = x.imag() != 0
print(x.is_imag)

Il est possible de rajouter des données


membres à une instance « à la volée » et de
les utiliser directement

90
Classe - Utilisation

x = MyComplex(3,2)

print(x.real() , " + i" , x.imag())

x.is_imag = x.imag() != 0
print( x.is_imag)

del x.is_imag

Il est possible enfin de « détruire » l’existence


d’une donnée membre

91
Une structure « à la C »
• Définition
• En C, les structure n’ont pas de fonctions membres

• Elle sont entièrement définies par la liste de leurs données membres


• L’équivalent python est une classe « vide » dont les membres seront ajoutés plus tard

class employee:
pass

john = Employee() # Création d'un employé vide

# Remplissage
john.name = 'John Doe'
john.dept = ‘Dpt informatique'
john.salary = 1000
92
Itérateurs

• Objectifs
• Les conteneurs PYTHON peuvent s’utiliser avec les boucles for … in …

• Il est parfois intéressant de doter ses propres classes de ce comportement

• Principes d’implantation :
• __iter__ qui est la fonction membre qui construit l’itérateur pour la boucle for
• __next__ qui est la fonction membre qui avance dans les données de votre classe

93
Itérateurs
class Reverse:
"""Parcours inverse d’une liste"""

def __init__(self, data):


self.data = data
self.index = len(data)

def __iter__(self):
return self

def __next__(self):
if self.index == 0:
raise StopIteration
self.index -= 1
return self.data[self.index]

>>> rev = Reverse('spam')


>>> for char in rev:
... print(char)
m
a
p 94
s
Classe – Surcharge d’opérateurs

class MyComplex:
def __add__(self, other):
res = MyComplex() On peut surcharger des membres
res.r = self.r + other.r de classes en définissant des
res.i = self.i + other.i fonctions membres avec des noms
return res spécifiques

x = MyComplex(4,3) On parle de Magic Functions


y = MyComplex(8,6)

r = x + y

95
Classe – Surcharge d’opérateurs
opération symbole méthode symbole méthode

addition + __add__(self,other) += __iadd__(self,other)

soustraction - __sub__(self,other) -= __isub__(self,other)

multiplication * __mul__(self,other) *= __imul__(self,other)

division / __truediv__(self,other) /= __itruediv__(self,other)

élévation à la
** __pow__(self,other) **= __ipow__(self,other)
puissance

division entière // __floordiv__(self,other) //= __ifloordiv__(self,other)

reste de la division
% __mod__(self,other) %= __imod__(self,other)
entière (modulo)

96
Classe – Surcharge d’opérateurs
opération symbole méthode
opposé - __neg__(self)
positif + __pos__(self)
valeur absolue abs() __abs__(self)

opération symbole méthode


égal == __eq__(self,other)
non égal != ou <> __ne__(self,other)
strictement inférieur < __lt__(self,other)
strictement supérieur > __gt__(self,other)
inférieur ou égal <= __le__(self,other)
supérieur ou égal >= __ge__(self,other)
97
Classe – Surcharge d’opérateurs
opération symbole méthode symbole méthode

addition + __add__(self,other) += __iadd__(self,other)

soustraction - __sub__(self,other) -= __isub__(self,other)

multiplication * __mul__(self,other) *= __imul__(self,other)

division / __truediv__(self,other) /= __itruediv__(self,other)

élévation à la
** __pow__(self,other) **= __ipow__(self,other)
puissance

division entière // __floordiv__(self,other) //= __ifloordiv__(self,other)

reste de la division
% __mod__(self,other) %= __imod__(self,other)
entière (modulo)

98
Interface et héritage

class Person:
def __init__(self, name):
self.name = name Les classes peuvent être
surchargées par héritage afin de
spécialier leur comportement
def getName(self):
return self.name Commençons par définir une classe
de Personne
def isEmployee(self):
return False

99
Interface et héritage
La classe Employee hérite de
class Person: Person via la notation Class(base)
def __init__(self, name):
self.name = name

def getName(self):
return self.name

def isEmployee(self):
return False

class Employee(Person):
def isEmployee(self):
return True
100
Interface et héritage
La classe Employee hérite de
class Person: Person via la notation Class(base)
def __init__(self, name):
self.name = name

def getName(self):
return self.name
La classe Employee ne fait que
redéfinir les fonctions membres
def isEmployee(self): dont le comportement change, les
return False autres sont fournies par la classe
de base, ici la classe Person

class Employee(Person):
def isEmployee(self):
return True
101
Interface et héritage
La classe Employee peut appeler
class Employee(Person): une fonction membre de sa classe
def isEmployee(self): mère en préfixant l’appel d’un
return True appel à super.

def __init__(self,name,salary)
self.salary = salary
super(Employee, self).__init__(name)

102
Exercices – Aspects Objets
• Fraction
• Créez une classe fraction qui se construit à partir de un ou deux entiers. Implémentez les
constructeurs nécessaires ainsi que les fonctions membres permettant d’ajouter,
multiplier, inverser, simplifier et afficher une fraction
• Modifiez votre classe fraction afin qu’elle puisse utilisée les opérateurs +,- et * en plus
de ses méthodes.
• Créez une classe safe_fraction qui hérite de fraction, simplifie automatiquement son
contenu et vérifie que son dénominateur est toujours non nul et non signé.
• Structurez l’ensemble des éléments de ces deux classes dans un module et écrivez les
tests unitaires nécessaires.

103
Outillage
Interactions avec le système
• Module os
• Large sélection de fonctions systèmes

>>> import os
>>> os.getcwd() # Repertoire de travail
'/home/bob/'

>>> os.chdir(os.path.join(“/home”,”bob”,”dev”))
>>> os.system('mkdir python-exo')

105
Interactions avec le système
• Module shutils
• Intéraction facilitée avec les fichiers

>>> import shutil


>>> shutil.copyfile('data.db', 'archive.db')
'archive.db’

>>> shutil.move(os.path.join(“/build”,”executables”), 'installdir')


'installdir'

106
Expressions Régulières
• Module re
• Expressions régulières pour recherche ou remplacement complexe dans les chaînes de caractères

>>> import re

>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')


['foot', 'fell', 'fastest’]

>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')


'cat in the hat'

107
Formules mathématiques
• Module math
• Accès aux fonctions mathématiques de la libc

>>> import math

>>> math.cos(math.pi / 4)
0.70710678118654757

>>> math.log(1024, 2)
10.0

108
Formules mathématiques
• Module random
• Fonction de génération de nombres aléatoires

• Fonction de choix aléatoire dans une collection


• Fonction d’échantillonage

>>> import random


>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10)
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random()
0.17970987693706186
>>> random.randrange(6)
4
109
Formules mathématiques
• Module statistics
• Fonction de calcul de grandeurs statistiques classiques sur des données numériques

>>> import statistics


>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> statistics.mean(data)
1.6071428571428572
>>> statistics.median(data)
1.25
>>> statistics.variance(data)
1.3720238095238095

110
Calcul scientifique avec NUMPY
• Objectifs
• Manipulation standardisée de tableau multidimensionnels

• Support pour les fonctions mathématiques, statistiques et d’algèbre linéaire


• Notion de slicing et de broadcasting

>>> import numpy as np


>>> e = np.array([(1,2,3), (4,5,6)])
[[1 2 3]
[4 5 6]]
>>> r = np.linalg.det( e[0:1,:] )
-3

111
Dates et Gestion du temps
• Module datetime
• Gestion des dates: formatage pour affichage, conversion, calcul de durée

>>> from datetime import date


>>> now = date.today()
>>> now
datetime.date(2003, 12, 2)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

>>> birthday = date(1964, 7, 31)


>>> other_date = date(2019, 10, 9)
>>> age = other_date - birthday
>>> age.days
20158 112
Connectivité internet & réseau
• Module urllib.request
• Permet d’émettre des requêtes via des URL et de consommer les réponses reçues

• Modules smtplib, poplib, email


• Gestion de manipulation de serveur mail ou de mail complet

from urllib.request import urlopen


with urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') as response:
for line in response:
line = line.decode('utf-8')
if 'EST' in line or 'EDT' in line:
print(line)

113

Vous aimerez peut-être aussi