- Itnroduction à la Programmation Orientée Objet (POO)
La programmation orientée objet est un paradigme qui utilise des objets et leurs interactions pour concevoir des applications et des programmes informatiques.
1.1 Concepts fondamentaux Classe : Une classe est un modèle ou un plan pour créer des objets. Elle définit des attributs et des méthodes communs à tous les objets de ce type. En Python, on définit une classe avec le mot-clé class, et le nom de la classe suit généralement une convention de PascalCase (première lettre de chaque mot en majuscule).
class Vehicule: # Définition d'une classe classique
pass
class Voiture(object): # Définition d'une classe moderne (hérite de object)
pass
Objet : Un objet est une instance concrète d'une classe. C'est une entité qui possède des attributs et des méthodes définis par sa classe. Par exemple, si Voiture est une classe, alors maVoiture serait un objet de cette classe.
Instance : Le terme instance est synonyme d'objet. Lorsque nous créons un objet à partir d'une classe, nous disons que nous instancions cette classe.
Attribut : Les attributs sont des variables associées à une classe ou à une instance. On distingue les attributs de classe (communs à toutes les instances) et les attributs d'instance (spécifiques à chaque objet).
Méthode : Une méthode est une fonction définie à l'intérieur d'une classe. Elle représente le comportement ou les fonctionnalités d'un objet.
Constructeur : Le constructeur est une méthode spéciale __init__ qui est appelée automatiquement lors de la création d'un objet. Il est utilisé pour initialiser les attributs de l'objet.
Voici un exemple illustratif :
class Animal:
def __init__(self, nom, espece): # Constructeur de la classe
self.nom = nom # Attribut d'instance
self.espece = espece
self.age = 0 # Attribut d'instance avec valeur par défaut
def crier(self): # Méthode d'instance
print(f"{self.nom} émet un son")
def vieillir(self): # Méthode d'instance
self.age += 1
print(f"{self.nom} a maintenant {self.age} an(s)")
# Création d'instances (objets)
chat = Animal("Félix", "Chat")
chien = Animal("Rex", "Chien")
# Utilisation des méthodes
chat.crier() # Affiche: Félix émet un son
chien.vieillir() # Affiche: Rex a maintenant 1 an(s)
1.2 Méthodes de classe, méthodes statiques et propriétés
Méthode de classe : Décorée avec @classmethod, une méthode de classe est liée à la classe plutôt qu'à une instance particulière. Elle peut accéder aux attributs de classe mais pas aux attributs d'instance.
class Ecole:
nombre_eleves = 0 # Attribut de classe
def __init__(self, nom):
self.nom = nom
Ecole.nombre_eleves += 1
@classmethod
def get_nombre_eleves(cls):
return f"Il y a {cls.nombre_eleves} élèves dans l'école"
@staticmethod
def verifier_age(age):
return age >= 18
@property
def nom_complet(self):
return f"L'école {self.nom}"
# Utilisation
ecole1 = Ecole("Jean Jaurès")
ecole2 = Ecole("Victor Hugo")
print(Ecole.get_nombre_eleves()) # Méthode de classe
print(Ecole.verifier_age(20)) # Méthode statique
print(ecole1.nom_complet) # Propriété (pas besoin de parenthèses)
1.3 Héritage
L'héritage permet de créer une nouvelle classe (classe dérivée) qui hérite des attributs et méthodes d'une classe existante (classe de base). La classe dérivée peut étendre ou modifier le comportement hérité.
class Forme:
def __init__(self, couleur):
self.couleur = couleur
def afficher_couleur(self):
print(f"Couleur: {self.couleur}")
class Rectangle(Forme):
def __init__(self, couleur, largeur, hauteur):
super().__init__(couleur) # Appel du constructeur de la classe de base
self.largeur = largeur
self.hauteur = hauteur
def calculer_aire(self):
return self.largeur * self.hauteur
def afficher_couleur(self): # Redéfinition de la méthode
super().afficher_couleur()
print("Je suis un rectangle")
# Utilisation
rectangle = Rectangle("rouge", 5, 3)
rectangle.afficher_couleur() # Utilise la méthode redéfinie
print(f"Aire: {rectangle.calculer_aire()}") # Méthode spécifique à Rectangle
1.4 Exemple pratique: Gestion d'une base de données
Voici une classe pour interagir avec une base de données MySQL en utilisant PyMySQL:
import pymysql
class GestionBaseDeDonnees:
def __init__(self, hote, utilisateur, mot_passe, base, port=3306, charset='utf8'):
try:
self.connexion = pymysql.connect(
host=hote,
user=utilisateur,
password=mot_passe,
port=port,
charset=charset,
db=base,
autocommit=True
)
self.curseur = self.connexion.cursor(cursor=pymysql.cursors.DictCursor)
except Exception as e:
print(f"Échec de la connexion à la base de données: {e}")
def executer_requete(self, requete):
try:
self.curseur.execute(requete)
resultat = self.curseur.fetchall()
return resultat
except Exception as e:
print(f"Erreur dans l'exécution de la requête: {e}")
return None
def __del__(self):
if hasattr(self, 'curseur'):
self.curseur.close()
if hasattr(self, 'connexion'):
self.connexion.close()
print("Connexion à la base de données fermée")
# Utilisation
db = GestionBaseDeDonnees('localhost', 'root', 'motdepasse', 'ma_base')
resultats = db.executer_requete('SELECT * FROM utilisateurs;')
if resultats:
for utilisateur in resultats:
print(f"ID: {utilisateur['id']}, Nom: {utilisateur['nom']}")
1.5 Exemple pratique: Génération de signature
Voici une approche orientée objet pour générer une signature à partir de données:
import hashlib
from urllib import parse
class GenerateurSignature:
def __init__(self, donnees_demande):
self.donnees_demande = donnees_demande
self.id_fournisseur = self.extraire_id_fournisseur()
def extraire_id_fournisseur(self):
paires = self.donnees_demande.split('&')
donnees_dict = {}
for paire in paires:
if '=' in paire:
cle, valeur = paire.split('=', 1)
donnees_dict[cle] = valeur
return donnees_dict.get('vendorId', '')
def calculer_md5(self, texte):
hacheur = hashlib.md5()
hacheur.update(texte.encode('utf-8'))
return hacheur.hexdigest()
def generer_signature(self):
# Premier MD5
premier_md5 = self.calculer_md5(self.id_fournisseur)
# Deuxième MD5
astr = self.calculer_md5(premier_md5)
# Encodage URL
url_encode = parse.quote_plus(self.donnees_demande)
# Signature finale
chaine_finale = astr + url_encode
signature = self.calculer_md5(chaine_finale)
return signature
# Utilisation
donnees = 'vendorId=1697&posCode=pos006&ip=127.0.0.1&posVersion=2.1.1.1.1&mac=;D4-81-D7-CA-20-29;7C-67-A2-9A-06-05;7C-67-A2-9A-06-06;7C-67-A2-9A-06-09;00-00-00-00-00-0000E0'
generateur = GenerateurSignature(donnees)
signature_finale = generateur.generer_signature()
print(f"Signature générée: {signature_finale}")
Cet exemple montre comment encapsuler la logique de génération de signature dans une classe, rendant le code plus modulaire et réutilisable.