Python est un langage de programmation orienté objet. Il est donc possible de définir des nouveaux types de données par le biais de classes. Pour de plus amples informations sur la programmation orientée objet en Python, je vous renvoie vers les tutoriels/cours associés.
L'exemple ci-dessous défini un nouveau type de données de manipulation de nombres rationnels (de fractions). On peut par exemple imaginer le rationnel 3/5 qui est constitué d'un numérateur, fixé à la valeur 3, et d'un dénominateur, qui lui est fixé à la valeur 5. Pour rappel, mathématiquement parlant, il est interdit de mettre un dénominateur à 0. L'objectif principal de la classe est de vérifier les changements d'états sur vos nombres rationnels afin de garantir qu'un objet ne soit jamais mis dans un état incohérent. Au pire, on déclenche une exception (une erreur). Pour réaliser ces contrôles, la classe utilise le concept de propriétés (repérable dans le code via les décorateurs Python, introduit par le caractère @).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#!/usr/bin/python3 # -*- coding: utf-8 -*- import math class Rational(object): def __init__(self, num: int=0, den: int=1): self.numerator = num self.denominator = den self.simplify() @property def numerator(self): return self.__numerator @numerator.setter def numerator(self, newNum): if not isinstance(newNum, int): raise TypeError("Numerator must be an integer") self.__numerator = newNum @property def denominator(self): return self.__denominator @denominator.setter def denominator(self, newDen): if not isinstance(newDen, int): raise TypeError("Denominator must be an integer") if newDen == 0: raise ValueError("Denominator cannot be zero") self.__denominator = newDen def simplify(self): pgcd = math.gcd(self.__numerator, self.__denominator) self.__numerator //= pgcd # Division entière self.__denominator //= pgcd def __str__(self): return f"[{self.__numerator}/{self.__denominator}]" def __add__(self, r2): return Rational( self.numerator*r2.denominator + self.denominator*r2.numerator, self.denominator * r2.denominator ) # Ajouter les méthodes __sub__ __mul__ __truediv__ def __lt__(self, r2): return self.numerator * r2.denominator < self.denominator * r2.numerator # Ajouter les méthodes __le__ __gt__ __ge__ __eq__ __ne__ def to_float(self): return self.__numerator / self.__denominator if __name__ == '__main__': r1 = Rational(1, 2) r2 = Rational(4,1) r = r1 + r2 print(r1, "+", r2, "=", r) to_simplify = Rational(100, 50) print("[100,50] ==", to_simplify) r = Rational() r.numerator = 33; r.denominator = 44; print("Prop: %s" % str(r)) try: bad = Rational(0, 0) except ValueError as e: print("An error is raised") |
Pour lancer cet exemple, veuillez procéder ainsi :
$> python Rational.py [1/2] + [4/1] == [9/2] [100,50] == [2/1] Prop: [33/44] An error is raised $>
Afin de bien tester cette classe, je vous propose de mettre en place une petite batterie de test unittest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import unittest from Rational import Rational class Test(unittest.TestCase): def setUp(self): print( "Avant chaque test" ) def tearDown(self): print( "Après chaque test" ) def testSimplify(self): r1 = Rational( 2*3*5*7*11, 3*5*7*13 ) assert r1.numerator == 22 assert r1.denominator == 13 def testAddition(self): r1 = Rational(1,3) r2 = Rational(2,1) result = r1 + r2 assert result.numerator == 7 assert result.denominator == 3 @unittest.expectedFailure def testBadDenominator(self): Rational( 1, 0 ) if __name__ == "__main__": #import sys;sys.argv = ['', 'Test.testName'] unittest.main() |
Une fois la classe de test codée, si vous utilisez l'IDE PyDev, cliquez avec le bouton droit de la souris sur le fichier de test (dans l'explorateur de projets). Sélectionnez-y "Run As", puis "Python Run". Cela lance le framework unittest. Une nouvelle vue (une nouvelle fenêtre) devrait s'ouvrir et afficher les résultats de votre batterie de tests. En voici une capture d'écran.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :