Fractions - 1re partie

Ce serait bien si nous pouvions utiliser Python pour additionner et multiplier des fractions tout comme nous pouvons le faire avec des entiers et d'autres types de nombres, n'est-ce pas ? Quelque chose comme :

>>> a = 1/2
>>> b = 1/4
>>> print a + b
3/4

En fait, nous pouvons enseigner à Python à faire quelque chose comme ça ! C'est ce que nous allons apprendre à faire dans cette leçon en plusieurs parties. Cela va être une leçon plutôt longue, mais nous allons apprendre pas mal de choses sur des parties très privées de Python.

Pour éviter d'avoir des bugs dans notre programme, nous allons procéder de façon systématique, en ajoutant seulement un petit peu de code nouveau à la fois, en utilisant une approche en trois étapes :

  1. Ajouter une nouvelle fonctionnalité.
  2. Vérifier que cela donne le résultat désiré, en testant avec des instructions print.
  3. Remplacer les instructions print par des instructions assert.

Répétez ces 3 étapes aussi souvent que nécessaire ! C'est un exemple de cas où il est normal de vous répéter !


Créer un nouveau type

Sans plus attendre, voici le code de base pour définir un nouveau type "fraction" et le tester.

  1 class Fraction(object):
2 def __init__(self, numerateur, denominateur=1):
3 self.num = numerateur
4 self.denom = denominateur
5 6 #== zone de test ci-dessous ===
7 8 if __name__ == "__main__":
9 a = Fraction(1, 2)
10 b = Fraction(3)
11 print a.num, a.denom
12 print b.num, b.denom
13 print a
14 print b

Jusqu'ici, vous devriez être capable de comprendre ce que fait ce code par vous-même. Remarquez l'utilisation d'un paramètre nommé à la ligne 2 pour que nous puissions passer un seul paramètre à Fraction() [comme nous le faisons en ligne 10] qui sera interprété comme un entier (divisé par 1). Si nous l'exécutons, nous obtiendrons la sortie suivante :

1 2
3 1
<__main__.Fraction object at 0x01530F30>
<__main__.Fraction object at 0x01530F50>

Les deux premières lignes sont comme nous les attendions. Mais les deux dernières, où nous avons essayé d'imprimer les fractions a et b, ne ressemblent pas exactement à ce que nous aurions aimé. Python ne sait pas comment nous voulons que l'objet apparaisse, alors il nous donne quelque chose comme le nom de variable qu'il utilise lui-même pour garder une trace de ces deux objets. Pour faire en sorte que Python imprime les fractions de la manière que nous voulons, nous devons lui dire d'utiliser l'une des méthodes privées.


Représenter les objets comme des chaînes

Pour dire à Python comment nous voulons que les objets soient imprimés, ou représentés comme des chaînes, nous utilisons la fonction __str__().

  1 class Fraction(object):
2 def __init__(self, numerateur, denominateur=1):
3 self.num = numerateur
4 self.denom = denominateur
5
6 def __str__(self):
7 return "(%s/%s)"%(self.num, self.denom)
8 9 #== zone de test ci-dessous ===
10 11 if __name__ == "__main__":
12 a = Fraction(1, 2)
13 b = Fraction(3)
14 print a
15 print b

Le résultat est :

(1/2)
(3/1)

À votre tour

Faites une modification à __str__() pour que si le dénominateur est 1, seul le numérateur est imprimé. Cela veut dire que, au lieu d'avoir "(3/1)", nous aurions simplement "3". Toutefois le résultat pour "(1/2)" devra rester inchangé.


Utilisation de assert

Maintenant que nous avons notre résultat désiré, nous remplaçons les instructions print par des instructions assert.

  1 class Fraction(object):
2 def __init__(self, numerateur, denominateur=1):
3 self.num = numerateur
4 self.denom = denominateur
5
6 def __str__(self):
7 return "(%s/%s)"%(self.num, self.denom)
8 9 #== zone de test ci-dessous ===
10 11 if __name__ == "__main__":
12 a = Fraction(1, 2)
13 b = Fraction(3)
14 assert str(a) == "(1/2)" 15 assert str(b) == "(3/1)"

Quand nous utilisons des assertions au lieu d'imprimer, nous devons comparer la représentation en chaîne str() au résultat attendu. Si vous exécutez ce programme, il ne devrait rien donner en sortie ; c'est ce que nous voulons ! Remarquez que j'ai encore utilisé le format avec le dénominateur toujours présent, "(3/1)", et non le format que je vous ai demandé de définir dans le dernier exercice.

Dans la suite, nous enseignerons à Python à multiplier des fractions !

début - Fractions - 2e partie suivant