ajout cours, tp et images POO
This commit is contained in:
243
POO/README.md
Normal file
243
POO/README.md
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
## Programmation orientée objet
|
||||||
|
|
||||||
|
> Concept fondamental dans la programmation moderne : **la Programmation Orientée Objet**, ou **POO** pour les intimes, est un changement de paradigme par rapport à ce qu’on a vu jusqu’ici.
|
||||||
|
|
||||||
|
Nous allons organiser notre programme en utilisant des **objets**.
|
||||||
|
|
||||||
|
Ces objets, c’est un peu comme des boîtes qui contiennent à la fois des **données** (des variables, qu’on appelle des **attributs**) et des **comportements** (des fonctions, qu’on appelle des **méthodes**).
|
||||||
|
|
||||||
|
Chaque objet va représenter une sorte de “petit être” autonome, capable de manipuler ses propres données et d’interagir avec d’autres objets.
|
||||||
|
|
||||||
|
L’idée principale derrière la POO, c’est de **modéliser le monde réel** ou des concepts abstraits en utilisant des **classes** et des objets. Une classe, c’est une sorte de plan ou de moule qui permet de créer des objets. Un peu comme un plan d’architecte pour construire des maisons : la classe, c’est le plan ; l’objet, c’est la maison.
|
||||||
|
|
||||||
|
## Le programme
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
## Rappel : Programmation impérative
|
||||||
|
|
||||||
|
La programmation impérative est un paradigme de programmation (une méthode de programmation) composé d'une suite d'instructions. C'est le type de programmation que l'on utilise jusqu'à présent. On retrouve ce paradigme dans les langages tels que Python, Javascript ou encore le langage C.
|
||||||
|
|
||||||
|
Si par exemple nous voulons créer un code qui utiliserait des étudiants, stockerait leurs spécialités, leur âge, leur nom, etc. Nous pourrions utiliser un dictionnaire par exemple.
|
||||||
|
|
||||||
|
```python
|
||||||
|
dico = {'Nom': 'Dupond','Prenom': 'Bob', 'Spe1' : 'NSI', 'Age': 17}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ici le dictionnaire contient des informations qui peuvent s'apparenter à un étudiant. Il est possible de changer les clés, les valeurs des clés. Mais en réalité nous manipulons un dictionnaire. Si nous vérifions le type de *dico* il s'agit d'un dictionnaire, non d'un étudiant.
|
||||||
|
|
||||||
|
La programmation objet va permettre, de créer un type *Etudiant* qui contiendra des caractéristiques qui lui sont propres (nommées **attributs**) et des fonction appropriées (nommées **méthodes**).
|
||||||
|
|
||||||
|
## Programmation orientée objet
|
||||||
|
|
||||||
|
La programmation orientée objet permet donc de créer son propre type. Le langage python possède nativement différents types tels que le type int, str, list (tableau), dict.
|
||||||
|
Ces types possèdent des méthodes, par exemple le type str possède la méthode *upper()* permettant de mettre en majuscules tous les caractères de la chaîne.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> s = 'Je suis un type str'
|
||||||
|
>>> s.upper()
|
||||||
|
'JE SUIS UN TYPE STR'
|
||||||
|
```
|
||||||
|
|
||||||
|
Le but ici est donc de réaliser la même chose sur un type que nous allons créer. (le type *Etudiant*)
|
||||||
|
|
||||||
|
Avant d'écrire la moindre ligne de code, il définir la classe :
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Etudiant :
|
||||||
|
```
|
||||||
|
|
||||||
|
> Il est important que le nom de la classe commence par une majuscule.
|
||||||
|
|
||||||
|
### Le constructeur
|
||||||
|
|
||||||
|
Le constructeur est une méthode(fonction) permettant d'initialiser votre type. Lorsque l'on va créer un étudiant c'est la méthode constructeur qui est appelée. En python elle est définie par '\_\_init\_\_()'
|
||||||
|
|
||||||
|
<u>Voici le constructeur pour notre classe *Etudiant* :</u>
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Etudiant :
|
||||||
|
def __init__(self,nom_etu,prenom_etu,spe1_etu,age_etu) :
|
||||||
|
self.nom = nom_etu
|
||||||
|
self.prenom = prenom_etu
|
||||||
|
self.spe1 = spe1_etu
|
||||||
|
self.age = age_etu
|
||||||
|
self.nom_complet = nom_etu + ' ' + prenom_etu
|
||||||
|
if self.age < 18 :
|
||||||
|
self.peut_avoir_son_permis = False
|
||||||
|
else :
|
||||||
|
self.peut_avoir_son_permis = True
|
||||||
|
```
|
||||||
|
|
||||||
|
Plusieurs choses sont à noter ici :
|
||||||
|
|
||||||
|
- *\_\_init\_\_* est une méthode de constructeur, son nom ne doit pas changer.
|
||||||
|
- ***self* est un paramètre que l'on retrouvera dans toutes les méthodes de nos classes.**
|
||||||
|
- *self* permet de désigner l'objet que l'on manipule
|
||||||
|
- ***nom, prenom, spe1, age, nom_complet, peut_avoir_son_permis* sont des **attributs** de la classe *Etudiant*
|
||||||
|
- Un étudiant est donc composé d'un nom, prénom, spe1, age, permis_voiture et d'un nom_complet.
|
||||||
|
- ***nom_etu,prenom_etu,spe1_etu,age_etu*** sont ici les paramètres de la fonction. Pas des attributs.
|
||||||
|
- L'attribut *peut_avoir_son_permis* est le résultat d'une condition.
|
||||||
|
- Il est possible de boucler, de mettre des conditions dans un constructeur
|
||||||
|
|
||||||
|
> Le constructeur est une fonction comme une autre, pouvant comporter des boucles, des conditions. L'utilité principale de celui-ci est avant tout de créer les attributs de notre objet.
|
||||||
|
|
||||||
|
A ce stade nous pouvons créer notre objet *Etudiant*
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> e = Etudiant('Dupond','Bob','NSI',17)
|
||||||
|
>>> e.nom
|
||||||
|
'Dupond'
|
||||||
|
>>> e.peut_avoir_son_permis
|
||||||
|
False
|
||||||
|
>>> e.age
|
||||||
|
17
|
||||||
|
```
|
||||||
|
|
||||||
|
> Le paramètre self correspond ici à e. Il n'apparait pas dans les parenthèses. Il s'agit de la variable stockant l'objet (e ici)
|
||||||
|
|
||||||
|
### Méthodes associées à la classe
|
||||||
|
|
||||||
|
Une fois notre constructeur crée il faut pouvoir manipuler l'objet. Ici nous pouvons accéder à ses attributs. Mais nous allons créer des méthodes permettant de changer, ajouter des attributs.
|
||||||
|
|
||||||
|
Supposons que l'étudiant change de spécialité. Bob voudrait arrêter de faire NSI (impossible, mais supposons pour l'exemple).
|
||||||
|
|
||||||
|
```python
|
||||||
|
def change_spe(self,nouvelle_spe) :
|
||||||
|
self.spe = nouvelle_spe
|
||||||
|
```
|
||||||
|
|
||||||
|
<u>Pour appeler la méthode :</u>
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> e.change_spe('SES')
|
||||||
|
```
|
||||||
|
|
||||||
|
> self est toujours présent lors de la définition de la méthode. Lors de l'appel, il s'agit toujours de e.
|
||||||
|
|
||||||
|
Il est possible d'écrire le code que l'on veut dans une méthode. Libre à votre imagination.
|
||||||
|
On pourrait créer une méthode *anniversaire* par exemple :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def anniversaire(self) :
|
||||||
|
self.age = self.age + 1
|
||||||
|
if self.age == 18 :
|
||||||
|
self.peut_avoir_son_permis = True
|
||||||
|
```
|
||||||
|
|
||||||
|
Si l'anniversaire de l'étudiant passe, alors il gagne 1 an et s'il a 18 ans alors il est éligible au permis de conduire.
|
||||||
|
|
||||||
|
Imaginons maintenant qu'il soit possible d'avoir une nouvelle spécialité.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def nouvelle_spe(self,new_spe):
|
||||||
|
self.spe2 = new_spe
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> etudiant2 = Etudiant('Timo','Alice','SES',17)
|
||||||
|
>>> etudiant2.spe1
|
||||||
|
'SES'
|
||||||
|
>>> e.nouvelle_spe(self,etudiant2.spe1)
|
||||||
|
>>> e.spe2
|
||||||
|
'SES'
|
||||||
|
```
|
||||||
|
|
||||||
|
Ici nous utilisons la spé de l'étudiant 2 (Alice) pour l'étudiant 1. Il y a peu intérêt dans cet exemple, mais il permet de démontré que c'est possible.
|
||||||
|
Un objet peut dépendre d'un autre, que cela soit dans un paramètre, un attribut, etc.
|
||||||
|
|
||||||
|
### Méthodes particulières
|
||||||
|
|
||||||
|
Avec un type natif à Python il est possible de faires certaines opérations. Par exemple, il est possible de comparer deux chaînes de caractères.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> s = 'oui'
|
||||||
|
>>> s2 = 'non'
|
||||||
|
>>> s == s2
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
<u>Comparer deux objets :</u>
|
||||||
|
|
||||||
|
Actuellement il est impossible de faire la même chose avec nos étudiants. C'est à nous de définir comment comparer (s'il y en a le besoin) nos objets.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def __eq__(self,obj2):
|
||||||
|
return self.spe1 == obj2.spe1
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette méthode propre à python permet d'effectuer l'opération suivante.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> e = Etudiant('Dupond','Bob','NSI',17)
|
||||||
|
>>> etudiant2 = Etudiant('Timo','Alice','SES',17)
|
||||||
|
>>> e == etudiant2
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
<u>Représenter un objet :</u>
|
||||||
|
|
||||||
|
Actuellement appeler un objet renvoie ceci :
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> e = Etudiant('Dupond','Bob','NSI',17)
|
||||||
|
>>> e
|
||||||
|
<__main__.Etudiant object at 0x03DC5890>
|
||||||
|
```
|
||||||
|
|
||||||
|
Avec la fonction *\_\_repr\_\_(self)* il est possible de donner une représentation à notre objet.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def __repr__(self):
|
||||||
|
return self.nom + ' ' + self.prenon
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> e = Etudiant('Dupond','Bob','NSI',17)
|
||||||
|
>>> e
|
||||||
|
Dupond Bob
|
||||||
|
```
|
||||||
|
|
||||||
|
> Il existe d'autres méthodes natives à python permettant d'effectuer tout type d'opération
|
||||||
|
|
||||||
|
<img src="assets/methode_speciale.png" alt="Méthodes_natives" style="zoom: 80%;" />
|
||||||
|
|
||||||
|
### Pour aller plus loin :
|
||||||
|
|
||||||
|
Il est possible de rendre les attributs privés. Actuellement nous pouvons modifier/ accéder aux attributs d'un objets simplement par son nom.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> e = Etudiant('Dupond','Bob','NSI',17)
|
||||||
|
>>> e.nom
|
||||||
|
'Dupond'
|
||||||
|
```
|
||||||
|
|
||||||
|
En utilisant des types privés il n'est plus possible d'accéder directement aux attributs d'un objets. Cette modification se passe dans le constructeur.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Etudiant :
|
||||||
|
def __init__(self,nom_etu,prenom_etu,spe1_etu,age_etu) :
|
||||||
|
self.__nom = nom_etu
|
||||||
|
self.__prenom = prenom_etu
|
||||||
|
self.spe1 = spe1_etu
|
||||||
|
self.age = age_etu
|
||||||
|
self.nom_complet = nom_etu + ' ' + prenom_etu
|
||||||
|
if self.age < 18 :
|
||||||
|
self.peut_avoir_son_permis = False
|
||||||
|
else :
|
||||||
|
self.peut_avoir_son_permis = True
|
||||||
|
```
|
||||||
|
|
||||||
|
Ici l'attribut \_\_nom et \_\_prenom sont privés. Pour accéder/modifier à leur valeur, il faut créer une méthode associée.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_nom(self):
|
||||||
|
return self.__nom
|
||||||
|
|
||||||
|
def set_nom(self,nouveau_nom):
|
||||||
|
self.__nom = nouveau_nom
|
||||||
|
```
|
||||||
|
|
||||||
|
Ces méthodes sont appelées des accesseurs et modificateurs. Elles sont optionnelles selon les cas.
|
||||||
52
POO/TP/TP_POO.md
Normal file
52
POO/TP/TP_POO.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# TP Programmation orientée objet
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 1. Introduction
|
||||||
|
|
||||||
|
Le but principal de ce TP est d'implémenter une classe Auteur. Ainsi qu'une classe Livre et Bibliothèque. Il y a volontairement pas/peu d'indication sur le code. Seuls les attributs et méthode **nécessaires** sont indiqués. Leurs implémentations sont libre et dépendent de chacun.
|
||||||
|
|
||||||
|
## 2. Classe Auteur
|
||||||
|
|
||||||
|
La classe Auteur est une classe ayant 2 ou 3 attributs selon l'auteur.
|
||||||
|
|
||||||
|
- Un nom (ou pseudonyme)
|
||||||
|
- Année de naissance
|
||||||
|
- Année de décès (s'il y a)
|
||||||
|
- Sinon mettre l'attribut à *False*
|
||||||
|
|
||||||
|
La classe *Auteur* ne possède pas de méthode.
|
||||||
|
|
||||||
|
## 3. Classe Livre
|
||||||
|
|
||||||
|
La classe livre possède différents attributs :
|
||||||
|
|
||||||
|
- Un titre
|
||||||
|
- Un genre (Policier, Fantastique ...)
|
||||||
|
- Un auteur **(qui doit être un objet *Auteur*)**
|
||||||
|
|
||||||
|
La classe *Livre* ne possède pas de méthode.
|
||||||
|
|
||||||
|
## 4. Classe bibliothèque
|
||||||
|
|
||||||
|
La classe bibliothèque possède deux attributs principaux :
|
||||||
|
|
||||||
|
- Un type de rayon (Policier, Fantastique ...)
|
||||||
|
- Des livres (représenté par un tableau par exemple) (Le tableau doit contenir des objets *Livre*)
|
||||||
|
|
||||||
|
La classe bibliothèque possède différentes méthodes :
|
||||||
|
|
||||||
|
- Une méthode permettant de savoir si un livre est disponible.
|
||||||
|
- Une méthode permettant de prêter un livre
|
||||||
|
- Une méthode permettant d'ajouter un livre dans son rayon.
|
||||||
|
|
||||||
|
## 5. Création des objets
|
||||||
|
|
||||||
|
Créer la classe est bien, maintenant il faut manipuler les objets.
|
||||||
|
|
||||||
|
1. **Créer 2 bibliothèques contenant chacune au moins 2 livres de deux auteurs différents.**
|
||||||
|
|
||||||
|
## 6. Pour aller plus loin
|
||||||
|
|
||||||
|
Ici, il est possible d'ajouter n'importe quel attributs et/ou méthodes de votre choix.
|
||||||
|
Il faut s'entraîner, essayer d'aller le plus loin possible. Alors essayez, testez !
|
||||||
97
POO/TP/TP_corrige.py
Normal file
97
POO/TP/TP_corrige.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
class Auteur :
|
||||||
|
def __init__(self,nom,naissance,deces = False):
|
||||||
|
"""
|
||||||
|
Méthode constructeur de Auteur.
|
||||||
|
param nom : (str) Nom de l'auteur
|
||||||
|
param naissance : (int) année de naissance de l'auteur
|
||||||
|
param deces : (int/bool) année de décès / False si toujours en vie"""
|
||||||
|
self.nom = nom
|
||||||
|
self.annee_naissance = naissance
|
||||||
|
self.deces = deces
|
||||||
|
|
||||||
|
class Livre :
|
||||||
|
def __init__(self,titre,genre,auteur):
|
||||||
|
"""Méthode constructeur de Livre
|
||||||
|
param titre : (str) Titre du livre
|
||||||
|
param genre : (str) Genre du livre
|
||||||
|
param auteur: (Auteur) Auteur du livre"""
|
||||||
|
self.titre = titre
|
||||||
|
self.genre = genre
|
||||||
|
self.auteur = auteur
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.titre
|
||||||
|
|
||||||
|
class Bibliotheque :
|
||||||
|
def __init__(self,rayon):
|
||||||
|
"""Méthode constructeur de bibliothèque. L'ensemble des livres est vide
|
||||||
|
lors de l'initialisation
|
||||||
|
param rayon : (str) Type de livre que la biblio peut recevoir"""
|
||||||
|
self.rayon = rayon
|
||||||
|
self.ens_livre = []
|
||||||
|
|
||||||
|
def add_livre(self,livre):
|
||||||
|
""" Méthode permettant d'ajouter un livre.
|
||||||
|
param livre (Livre): Livre à ajouter
|
||||||
|
return : (str) précise si le livre est ajouté ou non"""
|
||||||
|
if livre.genre == self.rayon :
|
||||||
|
self.ens_livre.append(livre)
|
||||||
|
return "Livre ajouté"
|
||||||
|
else :
|
||||||
|
return "Impossible d'ajouter le livre"
|
||||||
|
|
||||||
|
def est_dispo(self,nom_livre):
|
||||||
|
"""Méthode parcourant l'ensemble des livres de la biblio pour savoir si
|
||||||
|
un livre est disponible
|
||||||
|
param nom_livre : (str) Nom du livre à rechercher
|
||||||
|
return : (int) Indice du livre si dispo, -1 sinon"""
|
||||||
|
i = 0
|
||||||
|
while i < len(self.ens_livre) :
|
||||||
|
if self.ens_livre[i].titre == nom_livre :
|
||||||
|
return i
|
||||||
|
i+=1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def prete_livre(self,nom_livre):
|
||||||
|
"""Méthode permettant de preter un livre s'il est dispo.
|
||||||
|
param nom_livre : (str) nom du livre à emprunter
|
||||||
|
return : (Livre/bool) Livre si emprunt possible, False sinon"""
|
||||||
|
val = self.est_dispo(nom_livre)
|
||||||
|
if val != -1 :
|
||||||
|
livre = self.ens_livre[val]
|
||||||
|
# Utilisation des slices pour supprimer le livre (Tester d'autres exemples
|
||||||
|
# si pas compris)
|
||||||
|
self.ens_livre = self.ens_livre[:val] + self.ens_livre[val+1:]
|
||||||
|
return livre
|
||||||
|
else :
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
#Initialisation des valeurs :
|
||||||
|
a1 = Auteur('Bob',1990)
|
||||||
|
a2 = Auteur('Alice', 1998,2009)
|
||||||
|
l1 = Livre('Livre NSI terminale','Cours','Bob')
|
||||||
|
l2 = Livre('Livre NSI premiere','Cours',a2)
|
||||||
|
l3 = Livre('Les animaux de compagnies','Animaux',a1)
|
||||||
|
l4 = Livre('Les animaux sauvages','Animaux',a2)
|
||||||
|
b1 = Bibliotheque('Cours')
|
||||||
|
b2 = Bibliotheque('Animaux')
|
||||||
|
|
||||||
|
|
||||||
|
# Ajout des livres dans biblio :
|
||||||
|
b1.add_livre(l1)
|
||||||
|
b1.add_livre(l2)
|
||||||
|
b1.add_livre(l3) #Impossible d'ajouter le livre
|
||||||
|
|
||||||
|
b2.add_livre(l3)
|
||||||
|
b2.add_livre(l4)
|
||||||
|
|
||||||
|
#Pret d'un livre
|
||||||
|
print(b1.ens_livre)
|
||||||
|
b1.prete_livre('Livre NSI terminale')
|
||||||
|
print(b1.ens_livre)
|
||||||
|
|
||||||
|
|
||||||
|
#Dispo d'un livre
|
||||||
|
b2.est_dispo('Les animaux de compagnies')
|
||||||
|
b1.est_dispo('Livre NSI terminale') # Pas dispo
|
||||||
BIN
POO/assets/bo.png
Normal file
BIN
POO/assets/bo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
BIN
POO/assets/classy.gif
Normal file
BIN
POO/assets/classy.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
POO/assets/methode_speciale.PNG
Normal file
BIN
POO/assets/methode_speciale.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
Reference in New Issue
Block a user