Vous êtes sur la page 1sur 83

Algorithmie vs.

Programmation

Algorithmie
• Solution « informatique » relative à un problème

• Suite d’actions (instructions) appliquées sur des données
• 3 étapes principales :
1. saisie (réception) des données
2. Traitements
3. restitution (application) des résultats

Programme
• Transcription d’un algorithme avec une syntaxe prédéfinie

• Python

• Même principes fondamentaux que les autres langages objets (Delphi, Java, C#, etc.)
• Python s’enrichit de bibliothèques de calcul spécialisées (mathématique, bio
informatique, etc.)
Mode compilé vs. mode interprété
Langage interprété : + portabilité application ; - lenteur (R,
VBA, Python...)
Langage compilé : + rapidité ; - pas portable
(solution possible : write once, compile anywhere ; ex.
Lazarus)
Langage pseudo-compilé : + portabilité plate-forme ; -
lenteur (?) (principe : write once, run anywhere ; ex. Java et
le principe JIT)

Python est interprété, il est irrémédiablement lent, mais...


on peut lui associer des librairies intégrant des fonctions
compilées qui, elles, sont très rapides.
Etapes de la conception d’un programme (Génie Logiciel)
1.Déterminer les besoins et fixer les objectifs : que doit faire le logiciel, dans
quel cadre va-t-il servir, quels seront les utilisateurs types ? On rédige un
cahier des charges avec le commanditaire du logiciel (Remarque :
commanditaire = maître d’ouvrage ; réalisateur = maître d’œuvre)
2.Conception et spécifications : quels sont les fonctionnalités du logiciel, avec
quelle interface ?
3.Programmation : modélisation et codage
4.Tests : obtient-on les résultats attendus, les calculs sont corrects, y a-t-il 

plantage et dans quelles circonstances ? (tests unitaires, tests 

d’intégration, etc.)
5.Déploiement : installer le chez le client (vérification des configurations, 

installation de l’exécutable et des fichiers annexes, etc.)
6.Maintenance : corrective, traquer les bugs et les corriger (patches) ; 

évolutive (ajouter des fonctionnalités nouvelles au logiciel : soit sur
l’ergonomie, soit en ajoutant de nouvelles procédures) 

PROGRAMMER EN PYTHON
Python est un langage de programmation interprété. Il est associé à un
interpréteur de commandes disponible pour différents OS (Windows,
Linux, Mac OS X, etc.)
C’est un « vrai » langage c.-à-d. types de données, branchements
conditionnels, boucles, organisation du code en procédures et
fonctions, objets et classes, découpage en modules.
Très bien structuré, facile à appréhender, c’est un langage privilégié
pour l’enseignement.
Mode d’exécution : transmettre à l’interpréteur Python le fichier script
« .py »

Python est associé à de très nombreuses librairies très performantes,


notamment des librairies de calcul scientifique (Numpy, SciPy, Pandas,
etc.).
BASES DE PYTHON
Types élémentaires de Python
• Numérique qui peut être int (entier) ou float (double). Les opérateurs applicables
sont : + , - , * , / (division réelle), ** (puissance) , % (modulo) , // (division entière)
• bool correspond au type booléen, il prend deux valeurs possibles True et False
(respecter la casse). Les opérateurs sont not (négation), and (ET logique), or (OU
logique)
ex. not(True)!False ; True and False!False ; etc.

• str désigner les chaînes de caractères. Une constante chaîne de caractère doit être
délimitée par des guillemets (ou des quotes)
ex. a"« tano » affecte la valeur « tano » à l’objet a qui devient donc une variable
de type chaîne de caractères. Une chaîne de caractère se comporte comme un
vecteur : len() pour connaître sa longueur, a[0]!« t », a[1:3]!« ano », a[2:]!« no
», etc.
• Remarque : pour connaître la classe d’un objet i.e. le type associé à un objet, on
utilise la fonction type(nom_objet)

ex. type(1.2)!renvoie la valeur ‘float’
Instanciation et affectation

Affectation simple
La seconde évite les ambiguïtés.
#typage automatique
a = 1.0
#typage explicite
a = float(1)

Affectations multiples
Pas fondamental

#même valeur pour plusieurs variables


a = b = 2.5
#affectations parallèles
a, b = 2.5, 3.2
Transtypage

Conversion en numérique
a = « 12 » # a est de type chaîne caractère
b = float(a) #b est de type float
N.B. Si la conversion n’est pas possible ex. float(« toto »), Python
renvoie une erreur
Conversion en logique
a = bool(« TRUE ») # a est de type bool est contient la valeur True
a = bool(1) # renvoie True également
Conversion en chaîne de caractères
a = str(15) # a est de type chaîne et contient « 15 »
Opérateurs de comparaison

Les opérateurs de comparaison servent à comparer des


valeurs de même type et renvoient un résultat de type
booléen.

Sous Python, ces opérateurs sont <, <=, >, >=, != , ==


ex. a = (12 == 13) # a est de type bool, il a la valeur False

N.B. On utilisera principalement ces opérateurs dans les


branchements conditionnels.
Saisie et affichage

Saisie
a = input(« Saisir votre valeur »)
a = float(a)

input() permet d’effectuer une saisie au clavier



Il est possible d’afficher un message d’invite

La fonction renvoie toujours une chaîne, il faut
convertir
Saisie et affichage

Affichage
#Affichage explicite
print(a)

• Un affichage multiple est possible


Ex. print(a,b) #affiche a et b
• L’affichage direct du contenu d’un tableau (liste)
est possible également.
Branchement conditionnel « if »

if condition:

bloc d’instructions
else:
bloc d’instructions

(1) Attention au : qui est primordial



(2) C’est l’indentation (le décalage par rapport à la
marge gauche) qui délimite le bloc d’instructions
(3) La partie else est facultative
Boucle « for »

for ne s’applique que sur une collection de


valeurs.
Ex. tuples, listes,... à voir plus tard.
On peut définir des boucles indicées en générant
une collection de valeurs avec range()
(1)range(4)!0 1 2 3
(2)range(1,4)!1 2 3
(3)range(0,5,2)!0 2 4
Boucle « for »

for indice in séquence:


bloc d’instructions

• Attention à l’indentation toujours



• On peut « casser » la boucle avec break

• On peut passer directement à l’itération suivante
avec continue • Des boucles imbriquées sont possibles

• Le bloc d’instructions peut contenir des conditions
Boucle « while »

while condition:

bloc d’instructions

Remarque :

• Attention à l’indentation toujours

• On peut « casser » la boucle avec break
Définition des fonctions

• Fonction#Bloc d’instructions

• Prend (éventuellement) des paramètres en
entrée (non typés)
• Renvoie une valeur en sortie (ou plusieurs
valeurs, ou pas de valeurs du tout : procédure)

Procédure = Fonction sans return


Définition des fonctions
def petit (a, b):
if (a < b):
d =a
else:
d =0
return d
• def pour dire que l’on définit une fonction
• Le nom de la fonction est « petit »

• Les paramètres ne sont pas typés

• Noter le rôle du :
• Attention à l’indentation

• return renvoie la valeur

• return provoque immédiatement la sortie de la fonction
Appels des fonctions

print(petit(10, 12))

print(petit(a=10,b=12))

print(petit(b=12, a=10))

print(petit(12, 10))
Valeur par défaut

• Affecter des valeurs aux paramètres dès la


définition de la fonction

• Si l’utilisateur omet le paramètre lors de
l’appel, cette valeur est utilisée

• Si l’utilisateur spécifie une valeur, c’est bien
cette dernière qui est utilisée
• Les paramètres avec valeur par défaut doivent
être regroupées en dernière position dans la liste
des paramètres
Valeur par défaut

def ecart(a,b,epsilon = 0.1):


d = math.fabs(a - b)

if (d < epsilon):
d =0
return d

ecart(a=12.2, b=11.9, epsilon = 1) #renvoie 0


ecart(a=12.2, b=11.9) #renvoie 0.3
La valeur utilisée est epsilon = 0.1 dans ce cas
Passage de paramètres
#écriture de la fonction
def modifier_non_mutable(a,b): Les paramètres sont toujours passés par
a=2*a référence (référence à l’objet), mais ils sont
b= 3* b modifiables selon qu’ils sont mutables
print(a,b) (dictionnaire*, liste*, etc.) ou non mutables
(types simples, tuples*, etc.).
#appel
x = 10

y = 15 modifier_non_mutable(x,y) 20 45
print(x,y)

#écriture de la fonction
10 15
def modifier_mutable(a,b):
a.append(8) [10, 8] [6]
b[0] = 6
print(a,b)

#appel pour les listes


[10, 8] [6]
lx = [10]
ly = [15]
modifier_mutable(lx,ly) * à voir plus tard
print(lx,ly)
Fonction renvoyant plusieurs valeurs (1)

return peut envoyer plusieurs valeurs simultanément.


La récupération passe par une affectation multiple.

#écriture de la fonction
def extreme(a,b): if (a < b):
return a,b
else:
return b,a

#appel
x = 10

y = 15
 vmin =10 et vmax=15
vmin,vmax = extreme(x,y)
print(vmin,vmax)
Fonction renvoyant plusieurs valeurs (1)

Remarque : Que se passe-t-il si nous ne mettons


qu’une variable dans la partie gauche de
l’affectation ?

#ou autre appel


v = extreme(x,y)
print(v) v = (10, 15)
#quel type pour v ?
print(type(v))

<class ‘tuple’>
v est un « tuple », une collection de valeurs, à
voir plus tard.
Fonction renvoyant plusieurs valeurs (2)
Nous pouvons aussi passer par une structure
intermédiaire telle que la liste ou le dictionnaire
d’objets. Les objets peuvent être de type différent, au
final l’outil est très souple. (nous verrons plus en
détail les listes et les dictionnaires plus loin)

#écriture de la fonction #écriture de la fonction


def extreme_liste(a,b): def extreme_dico(a,b):
if (a < b): if (a < b):
return [a,b] return {'mini' : a,'maxi' : b}
else:
else:
return {'mini' : b,'maxi' : a}
return [b,a]

#appel #appel
x = 10
 x = 10

y = 15
 y = 15

res = extreme_liste(x,y) res = extreme_dico(x,y)
print(res[0])
print(res['mini'])
Visibilité (portée) des variables
1. Les variables définies localement dans les fonctions sont
uniquement visibles dans ces fonctions.

2. Les variables définies (dans la mémoire globale) en dehors de
la fonction ne sont pas accessibles dans la fonction

3. Elles ne le sont uniquement que si on utilise un mot clé
spécifique
#fonction #fonction #fonction
def modif_1(v): def modif_2(v): def modif_3(v):
x=v x=x+v
global x
#appel x=x+v
#appel x = 10
x = 10 modif_2(99) #appel
modif_1(99) print(x) x = 10
print(x)# 10 modif_3(99)
x n’est pas assignée ici,
l’instruction provoque une ERREUR
print(x)# 109
Imbrication des fonctions

Il est possible de définir une fonction dans une autre


fonction. Dans ce cas, elle est locale à la fonction,
elle n’est pas visible à l’extérieur.
#écriture de la fonction
def externe(a):
#fonction imbriquée
def interne(b): La fonction interne() est imbriquée
dans externe, elle n’est pas
return 2.0* b
exploitable dans le prog. principal
#on est dans externe ici ou dans les autres fonctions.
return 3.0 * interne(a)

#appel
x = 10

print(externe(x)) # renvoie 60
print(interne(x)) # provoque une erreur
Principe des Modules
• Un module est un fichier « .py » contenant un
ensemble de variables, fonctions et classes que l’on peut
importer et utiliser dans le programme principal (ou
dans d’autres modules).

• Le mot clé import permet d’importer un module
• C’est un pas supplémentaire vers la modularité : un
module maximise la réutilisation et facilite le partage du
code
• Des modules standards prêts à l’emploi sont livrés
avec la distribution Python. Ex. random, math, os,
hashlib, etc.

• Ils sont visibles dans le répertoire « Lib » de Python
Exemple d’utilisation de modules standards
#importer les modules
#math et random
import math, random

#génerer un nom réel


#compris entre 0 et 1
random.seed(None)
value = random.random()

#calculer le carré de



#son logarithme

logv = math.log(value)
abslog = math.pow(logv,2.0)

#affichage
print(abslog)
Autres utilisations possibles

#importer le contenu

#définition d'alias #des modules

import math as m, random as r from math import log, pow

from random import seed, random
#utilisation de l'alias
r.seed(None)
 #utilisation directe
value = r.random()
 seed(None)

logv = m.log(value) value = random()

logv = log(value)
abslog = m.pow(logv,2.0)
abslog = pow(logv,2.0)
LES TUPLES Tableau statique en lecture seule d’objets hétérogènes


#plage d'indices
#définition d'un
b = t1[2:5]
tuple
print(b)
t1 = (2,6,8,10,15,26)
#autre plage
print(t1)

#taille du tuple c = t1[:4]
print(c)
print(len(t1))
#indiçage négatif
#accès indicé
a = t1[0] d = t1[-1]
print(a) print(d)
#modification ? #indiçage négatif
t1[2] = 3
 ERREUR e = t1[-3:]
print(e)
Plus loin avec les tuples

#concaténation
t2 = (7, 9,31)
t3 = t1 + t2
print(t3)
#réplication
t4 = 2 * t2
print(t4)
#tuples d'objets hétérogènes
v1 = (3,6,"toto",True,34.1)
print(v1)
Plus loin avec les tuples

#tuple de tuples
x = ((2,3,5),(6,7,9),(1,8))
print(x)
#accès indicé
print(x[2][1])
#accès aux tailles
print(len(x))
print(len(x[2]))
LES LISTES
Liste ≈ tuple de taille dynamique et modifiable

#définition d'une liste Les autres mécanismes associés aux


L1 = [2,6,8,10,15,26] tuples sont transposables aux listes :
print(L1)
#taille de la tuple = 6
print(len(L1))
• plages d’indices

#accès indicé = 2
• indiçages négatifs
a = L1[0] • objets hétérogènes
print(a)
• liste de listes (tableaux 2D ou +)
#modification ! Possible ! • concaténation, réplication
L1[2] = 3
print(L1)
Plus loin avec les listes


#autre liste #accès + suppression elt n°1
L2 = [32,69,28,69] a = L2.pop(1)
#ajout
[32,69,69,21]
L2.append(21)

print(L2) print(a) ! renvoie 53
[32,69,28,69,21] #inversion


 L2.reverse()

#insertion à l'indice 1 print(L2)
L2.insert(1,53) [21,69,69,32]
print(L2) #étendre

[32,53,69,28,69,21] L2.extend([34,55])

print(L2)
[21,69,69,32,34,55]
#suppression elt n°3
del L2[3]
 #Permet de vider la liste
print(L2) L2.clear()
[32,53,69,69,21]
Les « List Comprehensions »
Objectif : un mécanisme simple (et concis) pour générer une liste à partir d’une autre liste.

source = [1,5,8,12,7]
resultat = []
for v in source: resultat = [v**2 for v in source]
resultat.append(v**2) print(resultat)
print(resultat)

source = [1,5,8,12,7]
resultat = []
for v in source:
if (v % 2 == 0):
resultat = [v**2 for v in source if (v % 2 == 0)]
resultat.append(v**2) print(resultat)
print(resultat)
Plus loin avec les listes
L2 = [21,69,69,32,34,55]
#recherche d'élément
trouve = 32 in L2
print(trouve)
#index
id = L2.index(34)
print(id)
#comptage
nb = L2.count(69)
print(nb)
#retrait par valeur
L2.remove(69)
print(L2)
Une variable de type liste est une référence

#L3
L3 = [61,92,17]

print(L3)

#affectation ?

L4 = L3

print(L4)

#modification d'une valeur L4[1] = 55
#répercussions
print(L4) ! [61,55,17] #mais aussi sur
L3

print(L3) ![61,55,17] ???
Une variable de type liste est une référence

#L3
L3 = [61,92,17]
#copie des valeurs
L4 = L3.copy() print(L4)
L4[1] = 55

print(L4) ! [61,55,17]
print(L3) ! [61,92,17] !!!
CHAÎNE DE CARACTÈRES
Une chaîne de caractères est une liste particulière avec des méthodes associées

#méthodes associées
#définir une chaîne S = s1.upper()
s1 = "bonjour le monde"
print(S)
print(s1)

#longueur
 #recherche d'une sous-chaîne
id = S.find("JO")

long = len(s1)
print(id)! 3 (1ère occurrence
print(long) si plusieurs)
#accès indicé #nb d'occurences

s2 = s1[:7] nb = S.count("ON")

print(nb)! 2

print(s2)
 #remplacement de « O » par « A »
#non modifiable
SA = S.replace("O","A")
#s1[0] = "B" print(SA)
Transformation explicite en liste
#transf. en liste
liste = list(S)
print(liste)
[‘B’,’O’,’N’,’J’,’O’,’U’,’R’,’ ‘,’L’,’E’,’ ‘,’M’,’O’,’N’,’D’,’E’]

#découpage par séparateur


decoupe = S.split(" ")
print(decoupe)
[‘BONJOUR’,’LE,’MONDE’]

#former une chaîne à


#partir d’une liste

SB = "-".join(decoupe)
print(SB)
"BONJOUR-LE-MONDE"
LES DICTIONNAIRES
Liste avec accès par clé

Dictionnaire : collection non-ordonnée (non indicée)


d’objets (simples ou évolués) s’appuyant sur le
mécanisme associatif
« clé – valeur ».
#définition d'un dictionnaire
d1 = {'Pierre':17, 'Paul':15,'Jacques':16}
print(d1)

#ou

print(d1.items())
#nombre d'élements #accès à une valeur par clé
print(len(d1))
print(d1['Paul'])
!3 éléments #ou
#liste des clés
print(d1.get('Paul'))
print(d1.keys())
#si clé n'existe pas Erreur
#liste des valeurs
print(d1['Pipa'])
print(d1.values())
 

Dictionnaire – Modifications, ajouts et suppressions
#modification
d1['Jacques'] = 18
print(d1)
{'Pierre':17, 'Paul':15,'Jacques':18}
#ajouter un élément
d1['Henri'] = 22
print(d1)
{‘Pierre':17, 'Paul':15,'Jacques':18, ‘Henri’:22}
#ajout d'un bloc d’éléments
d1.update({'Monica':36,'Bill':49})
print(d1)
{'Pierre':17, 'Paul':15,'Jacques':18, ‘Henri’:22, ‘Monica’:36, ‘Bill’ : 49}
#détecter présence clé
test = 'Pierre' in d1 print(test) True
#suppression par clé
del d1['Monica']
print(d1)
{'Pierre':17, 'Paul':15,'Jacques':18, ‘Henri’:22, ‘Bill’ : 49}
LES CLASSES SOUS PYTHON
Une classe est un type permettant de regrouper dans la même
structure : les informations (champs, propriétés, attributs)
relatives à une entité ; les procédures et fonctions permettant de
les manipuler (méthodes). Champs et méthodes constituent les
membres de la classe.

Termes techniques :

• « Classe » est la structure ;

• « Objet » est une instance de la classe (variable obtenue après instanciation) ;

• « Instanciation » correspond à la création d’un objet

• L’objet est une référence (traité par le ramasse-miettes, destruction explicite
inutile)
Définition et implémentation d’une classe

Ex. ModulePersonne.py #saisie des infos


def saisie(self):

#début définition self.nom = input("Nom : ")

self.age = int(input("Age : "))
class Personne:

self.salaire =
"""Classe Personne""" float(input("Salaire : "))
#constructeur #fin saisie
def __init__(self): #affichage des infos
#lister les champs def affichage(self):

self.nom = "" print("Son nom est ", self.nom)
self.age = 0 print("Son âge : ", self.age)
self.salaire = 0.0 print("Son salaire : ", self.salaire)
#fin constructeur #fin affichage
#fin définition
Définition et implémentation d’une classe
• class est un mot clé permettant de définir la structure
• Personne est le nom de la classe ici

• """Classe Personne""" sert à documenter la classes

• Regarder le rôle des « : » et des indentations
• __init__ est une méthode standard appelée constructeur, automatiquement
appelée lors de l’instanciation

• self représente l’instance elle-même, elle doit apparaître en première
position dans la définition de toutes les méthodes, mais il ne sera pas
nécessaire de la spécifier lors de l’appel
• nous exploitons le constructeur pour énumérer les champs de la classe
(pas obligatoire, mais bonne habitude à prendre), ils sont non typés

• le constructeur peut prendre des paramètres en entrée. Ex. initialisation
des champs
• contrairement aux autres langages, un seul constructeur par classe
seulement

• noter le rôle du « . » dans l’accès aux champs
Instanciation et utilisation dans le programme principal
# -*- coding: utf -*-
#appel du module
import ModulePersonne as MP
#instanciation
p = MP.Personne()

#affiche tous les membres de p
print(dir(p))
#affectation aux champs
p.nom = input("Nom : ")

p.age = int(input("Age : "))
p.salaire = float(input("Salaire : "))
#affichage
print(p.nom,", ",p.age,", ",p.salaire)
#saisie
p.saisie()
#méthode affichage
p.affichage()
COLLECTION D’OBJETS
# -*- coding: utf -*-
#appel du module
import ModulePersonne as MP
#liste vide
liste = []
#nb. de pers ?
n = int(input("Nb de pers : "))
#saisie liste
for i in range(0,n):
a = MP.Personne() Créer l’objet référencé par a,
Effectuer la saisie.
a.saisie()
Ajouter la référence dans la liste.
liste.append(a)
#affichage
print("*** début affichage 1")
Le typage est automatique,
for p in liste:
p est bien de type Personne.
print("-------")
p.affichage()
Accès indicé et modification des objets

#accès par numéro


numero = int(input("N° ind. à traiter :"))
Vérifier toujours que
if (numero < len(liste)): l’indice utilisé est valide.

b = liste[numero] Récupération de la référence


de l’objet, indice = numéro
b.salaire = b.salaire * 2
#affichage de nouveau liste[numero].salaire = ...
fonctionne également !
print("xxx début affichage 2")

for p in liste:
print("-------")
p.affichage()
else:

print("indice non valable")
Une fonction peut renvoyer un objet (instance de classe)

#début définition
class Personne:
"""Classe Personne"""
...
#copie des infos
def copie(self):

q = Personne()
q.nom = self.nom

q.age = self.age
q.salaire = self.salaire
return q
#fin copie
#fin définition
Une fonction peut renvoyer un objet (instance de classe)

#instanciation
p = MP.Personne()
#saisie
p.saisie()

print(">> Affichage de p")

p.affichage()

#copie

q = p.copie()

print(">> Affichage de q")

q.affichage()

#comp. références

pareil = (p == q)

print("ref. identiques : %s" % (pareil))
Héritage

Idée : L’héritage permet de construire une hiérarchie de classes. Les


classes héritières héritent des champs et méthodes de la classe
ancêtre.

#Ce mécanisme nécessite des efforts de modélisation et de
conception. Mais au final, on améliore la lisibilité et la réutilisabilité
du code.
Héritage
La classe Employe est une
Personne, avec le champ
supplémentaire prime. Cela va
nécessiter la reprogrammation des
méthodes saisie() et affichage().
On peut éventuellement ajouter
d’autres méthodes spécifiques à
Employe.

Déclaration en Python

class Employe(Personne):
...
Surcharge des méthodes
#classe Employé
class Employe(Personne): Surtout pas de copier/coller de code !
#constructeur Noter comment sont réutilisées les
méthodes programmées dans la classe
def __init__(self):
ancêtre Personne.

Personne.__init__(self) Remarque : Noter l’utilisation de self dans
self.prime = 0.0 ce contexte.
#fin constructeur
#saisie # -*- coding: utf -*-
def saisie(self): #appel du module
Personne.saisie(self)
 import ModulePersonne as MP
self.prime = float(input("Prime : ")) #instanciation
#fin saisie e = MP.Employe()
#affichage #saisie
def affichage(self): e.saisie()
Personne.affichage(self) #affichage
print("Sa prime : ", self.prime) print(">> Affichage")
#fin affichage #fin classe Employé e.affichage()
polymorphisme
# -*- coding: utf -*-
#appel du module

import ModulePersonne as MP
liste = [] #liste vide
n = int(input("Nb de pers : ")) #nb. de pers ?
#instanciation
for i in range(0,n):

code = input("1 Personne, 2 Employé : ")
if (code == "1"):
m = MP.Personne()
else:
m = MP.Employe()
liste.append(m)
#saisie liste
for p in liste:
Selon la classe réellement instanciée
print("-------")
p.saisie() (Employe ou Personne), les méthodes saisie()
#affichage et affichage() adéquates seront appelées.
for p in liste: C’est l’idée du polymorphisme.
print("-------")
p.affichage()
Variable de classes

Une variable de classe est un champ


directement accessible sur la classe, et qui
est partagée par toutes les instances de la
classe.
Variable de classes
#début définition
class Personne:
"""Classe Personne"""
#variable de classe
compteur = 0
#constructeur
def __init__(self):
#lister les champs
self.nom = ""
self.age = 0
self.salaire = 0.0
Personne.compteur += 1
#fin constructeur
...
#fin définition
Variable de classes

# -*- coding: utf -*-


#appel du module

import ModulePersonne as MP
#print compteur
print(MP.Personne.compteur) 0
#1ere instanciation
p = MP.Personne()
print(p.compteur) 1
#2nde instanciation

q = MP.Personne()
print(q.compteur) 2 

#de nouveau compteur
print(MP.Personne.compteur) 2
Variable de classes
#affectation 1
MP.Personne.compteur = 13
print(MP.Personne.compteur) !13
print(p.compteur) !13
print(q.compteur) !13
#affectation 2
p.compteur = 66
print(MP.Personne.compteur) !13
print(p.compteur) !66
print(q.compteur) !13
Numpy ?
• Numpy est un package pour Python spécialisé dans la
manipulation des tableaux (array), pour nous essentiellement les
vecteurs et les matrices

• Les tableaux « numpy » ne gère que les objets de même type

• Le package propose un grand nombre de routines pour un accès
rapide aux données (ex. recherche, extraction), pour les
manipulations diverses (ex. tri), pour les calculs (ex. calcul
statistique)
• Les tableaux « numpy » sont plus performants (rapidité, gestion
de la volumétrie) que les collections usuelles de Python

• Les tableaux « numpy » sont sous-jacents à de nombreux
packages dédiés au calcul scientifique sous Python.
• Attention, un vecteur est en réalité une matrice à 1 seule
dimension
CRÉATION D’UN VECTEUR
import numpy as np
np sera l’alias utilisé pour accéder aux routines de la librairie « numpy ».
Noter le rôle des [ ] pour délimiter les valeurs
a = np.array([1.2,2.5,3.2,1.8])
Informations sur la structure
#type de la structure
print(type(a)) #<class ‘numpy.ndarray’>
#type des données

print(a.dtype) #float64

#nombre de dimensions
print(a.ndim) #1 (on aura 2 si matrice, etc.)

#nombre de lignes et col

print(a.shape) #(4,)!on a tuple ! 4 cases sur la 1ère dim (n°0)
#nombre totale de valeurs
print(a.size) #4, nb.lignes x nb.colonnes si matrice
Typage des données
#création et typage implicite
a = np.array([1,2,4])
print(a.dtype) #int32
#création et typage explicite – préférable !
a = np.array([1,2,4],dtype=float)
print(a.dtype) #float64

print(a) #[1. 2. 4.]
#un vecteur de booléens est tout à fait possible
b = np.array([True,False,True,True], dtype=bool)
print(b) #[True False True True]
# la donnée peut être un objet python
a = np.array([{"Toto":(45,2000)},{"Tata":(34,1500)}])
print(a.dtype) #object
Création d’une séquence de valeurs
#suite arithmétique de raison 1
a = np.arange(start=0,stop=10)

print(a) #[0 1 2 3 4 5 6 7 8 9], attention dernière valeur est exclue
#suite arithmétique de raison step
a = np.arange(start=0,stop=10,step=2) print(a) #[0 2 4 6 8]
#suite linéaire, nb. de valeurs est spécifié par num

a = np.linspace(start=0,stop=10,num=5)

print(a) #[0. 2.5 5. 7.5 10.], la dernière valeur est incluse ici
#vecteur de valeurs identiques 1 – 1 seule dim et 5 valeurs
a = np.ones(shape=5)
print(a) # [1. 1. 1. 1. 1.]
#plus généralement – répétition 5 fois (1 dimension) de la valeur 3.2
a = np.full(shape=5,fill_value=3.2)
print(a) #[3.2 3.2 3.2 3.2 3.2]
Chargement à partir d’un fichier
#charger à partir d'un fichier

#typage explicite possible

a = np.loadtxt("vecteur.txt",dtype=float)
Remarque : si besoin, modifier le répertoire par défaut avec la fonction
chdir() du module os (qu’il faut importer au préalable)
print(a) #[4. 5. 8. 16. 68. 14. 35.]
Conversion d’une collection (type standard Python) en type array de «
numpy »
#liste de valeurs
lst = [1.2,3.1,4.5]

print(type(lst)) #<class ‘list’>
#conversion à partir d'une liste

a = np.asarray(lst,dtype=float)
print(type(a)) #<class ‘numpy.ndarray’>
print(a) #[1.2 3.1 4.5]
Redimensionnement
#vecteur de valeurs
a = np.array([1.2,2.5,3.2,1.8])
#ajouter une valeur , placée en dernière position
a = np.append(a,10)

print(a) #[1.2 2.5 3.2 1.8 10.]
#suppression via indice
b = np.delete(a,2) #une plage d’indices est aussi possible
print(b) #[1.2 2.5 1.8 10.]
a = np.array([1,2,3])
#redimensionnement

#1 valeur pour vecteur, couple de valeurs pour matrice
a.resize(new_shape=5)

print(a) #[1 2 3 0 0], les nouvelles cases mises à 0
#concatenation 2 vecteurs
x = np.array([1,2,5,6])

y = np.array([2,1,7,4])

z = np.append(x,y)

print(z) #[1 2 5 6 2 1 7 4]
Accès indicé – Plages d’indices
#toutes les valeurs
v = np.array([1.2,7.4,4.2,8.5,6.3])
print(v)
#ou
print(v[:]) # noter le rôle du : , il faut lire ici début à fin
#accès indicé - première valeur
print(v[0]) # 1.2 – Noter que le 1er indice est 0 (zéro)
#dernière valeur
print(v[v.size-1]) #6.3, v.size est ok parce que v est un vecteur
#plage d'indices contigus
print(v[1:3]) # [7.4 4.2] #extrêmes, début à 3 (non-inclus)
print(v[:3]) # [1.2 7.4 4.2] #extrêmes, 2 à fin
print(v[2:]) # [4.2 8.5 6.3] #indice négatif
print(v[-1]) # 6.3, dernier élément
#indices négatifs
print(v[-3:]) # [4.2 8.5 6.3], 3 derniers éléments
Accès indicé – Ecriture générique
v = np.array([1.2,7.4,4.2,8.5,6.3])
La notation générique des indices est : début:fin:pas
fin est non inclus dans la liste

#valeur n°1 à n°3 avec un pas de 1


print(v[1:4:1]) # [7.4, 4.2, 8.5]
#le pas de 1 est implicite
print(v[1:4]) # [7.4, 4.2, 8.5]
#n°0 à n°2 avec un pas de 2
print(v[0:3:2]) # [1.2, 4.2]

#le pas peut être négatif, n°3 à n°1 avec un pas de -1
print (v[3:0:-1]) # [8.5, 4.2, 7.4]
#on peut exploiter cette idée pour inverser un vecteur
print(v[::-1]) # [6.3, 8.5, 4.2, 7.4, 1.2]
Accès par conditions
v = np.array([1.2,7.4,4.2,8.5,6.3])
#extraction avec un vecteur de booléens

#si b trop court, tout le reste est considéré False

b = np.array([False,True,False,True,False],dtype=bool)
print(v[b]) # [7.4 8.5]
#on peut utiliser une condition pour l'extraction
print(v[v < 7]) # [1.2 4.2 6.3]
#parce que la condition est un vecteur de booléen
b= v< 7

print(b) # [True False True False True]
print(type(b)) # <class ‘numpy.ndarray’>
#on peut utiliser la fonction extract()
print(np.extract(v < 7, v)) # [1.2 4.2 6.3]
Tri et recherche
v = np.array([1.2,7.4,4.2,8.5,6.3])
#recherche valeur max
print(np.max(v)) # 8.5
#recherche indice de valeur max
print(np.argmax(v)) # 3
#tri des valeurs
print(np.sort(v)) # [1.2 4.2 6.3 7.4 8.5]
#récupération des indices triés
print(np.argsort(v)) # [0 2 4 1 3]
#valeurs distinctes
a = np.array([1,2,2,1,1,2])
print(np.unique(a)) # [1 2]
Calculs (statistiques)
v = np.array([1.2,7.4,4.2,8.5,6.3])
#moyenne
print(np.mean(v)) # 5.52
#médiane
print(np.median(v)) # 6.3
#variance
print(np.var(v)) # 6.6856
#quantile
print(np.percentile(v,50)) #6.3 (50% = médiane)
#somme
print(np.sum(v)) # 27.6
#somme cumulée
print(np.cumsum(v)) # [1.2 8.6 12.8 21.3 27.6]

Calculs entre vecteurs

#calculs entre vecteurs #opérations logiques

x = np.array([1.2,1.3,1.0])
 a = np.array([True,True,False,True],dtype=bool)
y = np.array([2.1,0.8,1.3]) b = np.array([True,False,True,False],dtype=bool)

#multiplication
 #ET logique



np.logical_and(a,b) # [True False False False]
print(x*y) # [2.52 1.04 1.3]
#OU exclusif logique
#addition
np.logical_xor(a,b) # [False True True True]
print(x+y) # [3.3 2.1 2.3]
#multiplication par un scalaire
print(2*x) # [2.4 2.6 2. ]
#comparaison de vecteurs
x = np.array([1,2,5,6])

y = np.array([2,1,7,4])

b = x> y

print(b) # [False True False True]
Fonctions matricielles
x = np.array([1.2,1.3,1.0])
y = np.array([2.1,0.8,1.3])
#produit scalaire
z = np.vdot(x,y) print(z) # 4.86
#ou l’équivalent calculé
print(np.sum(x*y)) # 4.86
#norme d'un vecteur
n = np.linalg.norm(x)
print(n) # 2.03
#ou l’équivalent calculé
import math
print(math.sqrt(np.sum(x**2))) # 2.03
Opérations ensemblistes

#opérations ensemblistes
x = np.array([1,2,5,6])
y = np.array([2,1,7,4])
#intersection
print(np.intersect1d(x,y)) # [1 2]

#union – attention, ce n’est pas une concaténation
print(np.union1d(x,y)) # [1 2 4 5 6 7]
#différence c.à-d. qui sont dans x et pas dans y
print(np.setdiff1d(x,y)) # [5 6]
CRÉATION D’UNE MATRICE
import numpy as np
a = np.array([[1.2,2.5],[3.2,1.8],[1.1,4.3]])
Noter le rôle des [ ] et [ ] pour délimiter les portions de la matrice
#type de la structure
print(type(a)) #<class ‘numpy.ndarray’>
#type des données

print(a.dtype) #float64

#nombre de dimensions
print(a.ndim) #2 (car c’est une matrice)
#nombre de lignes et col, shape renvoie un tuple
print(a.shape) #(3,2)!3 lignes et 2 colonnes
#nombre totale de valeurs

print(a.size) #6, nb.lignes x nb.colonnes
Création d’une matrice à partir d’une séquence
#création à partir d'une séquence. Les dim. doivent être compatibles
a = np.arange(0,10).reshape(2,5)

print(a)
#un vecteur peut être converti en matrice
a = np.array([2.1,3.4,6.7,8.1,3.5,7.2])
print(a.shape) # (6,)

#redim. en 3 lignes x 2 col.

b = a.reshape(3,2)
print(b.shape) # (3, 2)
print(b)
#matrices de valeurs identiques
#ex. pour une initialisation

a = np.zeros(shape=(2,4))
print(a)
#plus généralement
a = np.full(shape=(2,4),fill_value=0.1)
print(a)
Chargement à partir d’un fichier
#charger à partir d'un fichier, typage explicite
#séparateur de colonne = tabulation « \t »

a = np.loadtxt("matrice.txt",delimiter="\t",dtype=float)
La première ligne doit être ignorée dans ce fichier, d’où le symbole # en début
de 1ère ligne.
Conversion d’une collection (type standard Python) en type
array de « numpy »
#liste de valeurs
lst = [1.2,3.1,4.5,6.3]

print(type(lst)) # <class ‘list’>

#conversion à partir d'une liste : 2 étapes asarray() et reshape()
a = np.asarray(lst,dtype=float).reshape(2,2)

print(a)
Redimensionnement
#matrice de valeurs
a = np.array([[1.2,2.5],[3.2,1.8],[1.1,4.3]])
#ajouter une ligne – marche pour la concaténation de matrices
b = np.array([[4.1,2.6]])

c = np.append(a,b,axis=0)
#ajouter une colonne
d = np.array([[7.8],[6.1],[5.4]])
print(np.append(a,d,axis=1))
#insertion
print(np.insert(a,1,b,axis=0))
#suppression
print(np.delete(a,1,axis=0))
#modifier la dimension d'une matrice existante
#parcourt les données lignes par ligne

np.resize(a,new_shape=(2,3))

Accès indicé – Plages d’indices
v = np.array([[1.2,2.5],[3.2,1.8],[1.1,4.3]])
print(v) #affichage de la structure dans son ensemble
#accès indicé - première valeur
print(v[0,0]) # 1.2

#dernière valeur – noter l’utilisation de shape (qui est un tuple)
print(v[v.shape[0]-1,v.shape[1]-1]) # 4.3

#autre solution pour affichage de toutes les valeurs, noter le rôle des :
print(v[:,:])
#plage d'indices contigus : lignes 0 à 1 (2 non inclus), toutes les colonnes
print(v[0:2,:])
#extrêmes, début to 2 (non-inclus)
print(v[:2,:])
#extrêmes, lignes 1 à dernière
print(v[1:,:])
#indice négatif – dernière ligne et toutes les colonnes
print(v[-1,:])
#indices négatifs – deux dernières lignes et toutes les colonnes
print(v[-2:,:])
Tri et recherche
#recherche valeur max des lignes (axis = 0) pour chaque colonne
print(np.max(v,axis=0)) # [ 3.2 4.3 ] -- décryptage : 3.2 est la max
des lignes pour la colonne 0, 4.3 est la max des lignes pour la
colonne 1
#recherche valeur max des colonnes (axis = 1) pour chaque ligne
print(np.max(v,axis=1)) # [ 2.5 3.2 4.3]

#recherche indice de valeur max des lignes (axis = 0)pour chaque
colonne
print(np.argmax(v,axis=0)) # [ 1 2 ]
#tri des lignes (axis = 0) pour chaque colonne

#la relation entre les valeurs d'une même ligne est perdue !!!
print(np.sort(v,axis=0))
#récupération des indices triés
print(np.argsort(v,axis=0))
Parcours d’une matrice : boucle indicées

#boucles indicées
s = 0.0

for i in range(0,v.shape[0]):
for j in range(0,v.shape[1]):
print(v[i,j])

s = s + v[i,j]
print("Somme = ",s)
Parcours d’une matrice : les itérateurs
#itérateur - accès ligne par ligne
s = 0.0

for x in np.nditer(v):
print(x)
s=s+x
print("Somme = ",s)
#itérateur - accès colonne par colonne
#"F" pour " Fortran order "
s = 0.0

for x in np.nditer(v,order="F"):
print(x)
s = s +x
print("Somme = ",s)
CALCUL MATRICIEL

#transposition
print(np.transpose(x))
#multiplication
print(np.dot(x,y))
#déterminant
print(np.linalg.det(y))
#inversion
print(np.linalg.inv(y))
CALCUL MATRICIEL

#résolution d'équation
z = np.array([1.7,1.0])
print(np.linalg.solve(y,z))
#vérification
print(np.dot(np.linalg.inv(y),z))
#matrice symétrique avec XTX
s = np.dot(np.transpose(x),x)
print(s)
#val. et vec. propres d'une matrice symétrique
print(np.linalg.eigh(s))

Vous aimerez peut-être aussi