POO, documentation et tests - TP4
Classes, objets, attributs et méthodes en Python
Introduction
Créer l’arborscence
Vous pouvez créer chaque dossier et fichier à la main, ou utiliser dans un terminal Git Bash les commandes ci-dessous (mkdir : make directory):
# Sur la VM ensai
mkdir -p /p/Cours1A/IPOO/TP4/Exercice_{1..3}/
# Sur un Datalab Onyxia
mkdir -p /home/onyxia/work/IPOO/TP4/Exercice_{1..3}/
Moodle
1 Cours
1.1 Classes et Objets
- une
classe
est comme un “moule” qui sert à fabriquer des objets - un
objet
est une instance de classe- il est créé via un appel au constructeur
- une classe est composée
- d’attributs : ce qu’elle est
- de méthodes : ce qu’elle peut faire
Important
- un nom de classe s’écrit en CamelCase (majuscule à chaque mot)
- une seule classe par module
- (module : fichier, package : dossier)
- le nom du module s’écrit en snake_case (mots en minuscules séparés par des underscores :
_
)
1.2 Exemple de classe
Définir la classe Frac
frac.py
class Frac:
def __init__(self, num, denom=1) -> None:
"""Constructeur"""
self.num = num
self.denom = denom
def add(self, autre_fraction) -> "Frac":
"""Additionne deux fractions"""
= self.num * autre_fraction.denom + autre_fraction.num * self.denom
numerateur = self.denom * autre_fraction.denom
denominateur return Frac(numerateur, denominateur)
def __str__(self) -> str:
"""Retourne une chaîne affichant la fraction"""
return f"{self.num} / {self.denom}"
Utiliser la classe Frac pour créer des objets
__main__.py
from frac import Frac
= Frac(1, 2)
f1 = Frac(1, 4)
f2
= f1.add(f2)
f3 print(f3)
1.3 self
Dans la définition d’une classe, self représente l’instance actuelle :
self.denom
: représente l’attirbut denom de l’objetdef add(self, autre_fraction)
: dans la définition de chaque méthode, le premier paramètre sera self- cependant lors de l’appel de la méthode self n’apparait pas :
f1.add(f2)
1.4 Méthodes
Les méthodes de classe sont des fonctions qui s’appliquent à un objet :
- la syntaxe est la suivante :
mon_objet.ma_methode()
- à ne pas confondre avec les fonctions classiques
ma_fonction(mon_objet)
Ces méthodes peuvent :
- obtenir / modifier les valeurs des attributs de l’objet
- retourner une valeur, un objet ou rien
Méthode | Description | Type de retour |
---|---|---|
__init__(self, num, den) |
Initialise un objet de type Fraction. | None |
get_numerateur(self) |
Retourne le numérateur de la fraction. | int |
get_denominateur(self) |
Retourne le dénominateur de la fraction. | int |
set_numerateur(self, num) |
Modifie le numérateur de la fraction. | None |
set_denominateur(self, den) |
Modifie le dénominateur de la fraction. | None |
__str__(self) |
Représentation en chaîne de caractères (ex: 3/4). | str |
simplifier(self) |
Simplifie la fraction en divisant par le PGCD. | Fraction |
to_decimal(self) |
Retourne la valeur décimale de la fraction. | float |
inverse(self) |
Retourne une nouvelle fraction inversée. | Fraction |
add(self, autre_fraction) |
Addition avec une autre fraction. | Fraction |
2 Templates
2.1 Classe
class MaClasse:
"""titre_ma_classe
Description
Attributes
----------
attribut_1 : type_attribut_1 (str, int, float, list, bool, function...)
desc_attribut_1
attribut_2 : type_attribut_2
desc_attribut_2
"""
def __init__(self, parametre_1, parametre_2):
"""Constructeur de l'objet
Parameters
----------
parametre_1 : type_parametre_1
desc_parametre_1
parametre_2 : type_parametre_2
desc_parametre_2
"""
self.attribut_1 = parametre_1
self.attribut_2 = parametre_2
def ma_methode(self, param1):
"""desc_courte_ma_methode
desc_longue_ma_methode_facultatif
Parameters
----------
param1 : type
desc_param_1
Returns
-------
type
desc_retour
Examples
--------
>>> mon_obj = ma_classe("toto")
>>> mon_obj.ma_methode("xxx")
2
"""
return 2
def __str__(self):
"""Conversion de l'objet en chaîne de caractères
Examples
--------
>>> mon_obj = ma_classe("toto")
>>> print(mon_obj)
Classe d'attribut_1 égal à toto
"""
return f"Classe d'attribut_1 égal à {self.attribut_1}"
2.2 Fonction
Voici un modèle que vous pouvez utiliser pour documenter vos fonctions
def ma_fonction(param1, param2):
"""description_courte
description_longue
Parameters
----------
param1 : type (str, int, float, list...)
description_param1
param2 : type
description_param2
Returns
-------
type_retour
description_retour
Examples
--------
>>> 1+1
2
>>> print("abc")
abc
>>> ma_fonction(xxx, yyy)
valeur_esperee
"""
return None
if __name__ == '__main__':
= ma_fonction(p1, p2)
a print(a)
2.3 TU avec pytest
import pytest
from mon_fichier import ma_fonction
@pytest.mark.parametrize(
'param1, param2, resultat_attendu',
[1, 1, 2),
(1, 2, 3),
(2, 2, 4)
(
]
)def test_ma_fonction(param1, param2, resultat_attendu):
assert ma_fonction(param1, param2) == resultat_attendu
3 Exercices
-
- dans votre Explorer à gauche apparait l’arborescence des dossiers et fichiers de Exercice_1
3.1 Exercice 1
-
>>> a1 = Voiture('titine', 'bleue') >>> a2 = Voiture('quatrelle','verte') >>> a2.accelere(18) >>> a3 = Voiture('bovelo','jaune') >>> a3.accelere(8) >>> print(a1) 'arrêt. Voiture titine de couleur bleue à l>>> print(a2) 10km/h. Voiture quatrelle de couleur verte roule à >>> print(a3) 8km/h. Voiture bovelo de couleur jaune roule à
Tip
Pour lancer les tests, plusieurs possibilités :
- Coller ceci en bas de votre classe, puis cliquer sur l’icone éxéctuer ▶️
if __name__ == '__main__':
import doctest
=True) doctest.testmod(verbose
- dans un terminal :
python -m pytest --doctest-modules
- utiliser l’interface de VSCode (à gauche icone Testing en forme de fiole)
3.2 Exercice 2
Remarque
En supposant que c1 et c2 sont deux instances de Complexe, ces deux lignes de code font exactement la même chose et renvoient le même résultat :
c1.__add__(c2)
c1 + c2