L'écriture de nombres non entiers sous forme de fractions a de loin précédé celle des nombres décimaux, puisque les égyptiens et les babyloniens les utilisaient déjà. Chaque fois que le dénominateur n'est pas une puissance de 10, on continue encore de nos jours à utiliser des écritures fractionnaires plus ou moins cachées, comme dans les exemples suivants :
L'égalité 0,2+0,5=0,7 peut s'écrire formula_3 mais l'égalité formula_4 ne peut pas s'écrire sous forme décimale exacte parce que le résultat n'est pas décimal. "Python" affiche 1/2+1/3=0.8333333333333333 et malgré l'abondance de chiffres, cette égalité n'est pas exacte.
Pour faire des calculs exacts avec des fractions, "Python" a un module "fractions.py". Pour transformer "Python" en un langage de programmation spécialisé dans les fractions, il suffit de précéder les scripts de ce chapitre de la ligne 
from fractions import *
qui importe le module "fractions" en entier (pourquoi faire dans le détail?). Une alternative est de chercher le fichier "__init__.py", initialement vide, et d'y mettre la ligne précédente.
Obtention d'une fraction.
Pour entrer la fraction formula_5 dans "Python", on entre "Fraction(n,d)" après avoir importé le module "fractions" :
from fractions import *
a=Fraction(24,10)
print(a)
On constate que la fraction formula_6 a été automatiquement simplifiée par "Python" au moment de son instanciation.
Si on entre 0 comme dénominateur, la fraction ne se crée pas et on a un message d'erreur : Comme une fraction est un quotient, on ne peut pas diviser par 0. 
Une fois qu'une fraction est calculée, on peut obtenir son numérateur et son dénominateur par 
from fractions import *
a=Fraction(24,10)
print(a.numerator)
print(a.denominator)
Bien entendu, le numérateur de formula_6 n'est pas 24...
Pour obtenir la valeur de la fraction (le quotient de son numérateur par son dénominateur), on peut lui additionner 0.0 : La somme d'une fraction et d'un réel, même nul, est un réel.
from fractions import *
a=Fraction(24,10)
print(a+0.0)
Réciproquement, on peut convertir un nombre réel en fraction, mais le résultat est parfois surprenant, si on prend un nombre dont le développement décimal s'arrête alors que le développement binaire ne le fait pas :
from fractions import *
a=Fraction.from_float(1.2)
print(a)
On s'attendait à formula_8, on a l'approximation un peu surprenante formula_9...
Opérations.
Les opérations sur les fractions se notent comme celles sur les autres nombres, mais en général le résultat est une fraction.
Opérations unaires.
Opposé.
L'opposée d'une fraction s'obtient en la faisant précéder du signe "-". Par exemple, la fraction suivante est positive :
from fractions import *
a=Fraction(2,-3)
print(-a)
Inverse.
Pour obtenir l'inverse d'une fraction, on divise 1 par celle-ci :
from fractions import *
a=Fraction(5,4)
print(1/a)
Addition.
La somme de deux fractions est une fraction :
from fractions import *
a=Fraction(34,21)
b=Fraction(21,13)
print(a+b)
Soustraction.
La différence de deux fractions est une fraction :
from fractions import *
a=Fraction(34,21)
b=Fraction(21,13)
print(a-b)
Multiplication.
Le produit de deux fractions est une fraction :
from fractions import *
a=Fraction(34,21)
b=Fraction(21,13)
print(a*b)
Division.
Le quotient de deux fractions est une fraction (à condition que la deuxième ne soit pas nulle) :
from fractions import *
a=Fraction(34,21)
b=Fraction(21,13)
print(a/b)
Le reste euclidien continue à être défini pour des fractions, et le résultat est une fraction :
from fractions import *
a=Fraction(32,7)
b=Fraction(7,2)
print(a%b)
Puissance.
Si l'exposant est entier, la puissance d'une fraction est une fraction :
from fractions import *
a=Fraction(3,2)
print(a**12)
print(a**(-1))
Mais si l'exposant est un réel, la puissance n'est pas une fraction mais un réel :
from fractions import *
a=Fraction(9,4)
print(a**0.5)
Algorithmes.
Réduite de Farey.
La création de réduite de Farey est aisée avec le module "fractions" de "Python":
from fractions import *
def Farey(a,b):
 n=a.numerator+b.numerator
 d=a.denominator+b.denominator
 return Fraction(n,d)
a=Fraction(5,4)
b=Fraction(1,13)
print(Farey(a,b))
C'est si facile qu'on en vient tout de suite à la question suivante : à quoi ça peut bien servir ?
Si on répond que ça sert à fabriquer un arbre de Stern-Brocot, ça n'éclaire peut-être pas beaucoup, mais disons que ça sert à quelque chose de mathématique...
Fractions égyptiennes.
Une fraction égyptienne est définie comme une somme d'inverses d'entiers. En effet les égyptiens avaient la réputation de ne pas utiliser de numérateurs. Toute fraction peut s'écrire comme une somme de fractions égyptiennes, et l'algorithme de Fibonacci permet d'en trouver un exemple à partir de la fraction. Dans la version "Python" ci-dessous, l'algorithme fournit une liste de fractions, toutes de numérateur 1, dont la somme est une fraction donnée "f". Mais au cas où "f" serait supérieure à 1, on commence la liste par un entier :
from fractions import *
from math import *
def egypt(f):
 e=int(f)
 f-=e
 liste=[e]
 while(f.numerator>1):
 e=Fraction(1,int(ceil(1/f)))
 liste.append(e)
 f-=e
 liste.append(f)
 return liste
a=Fraction(21,13)
print(egypt(a))
Quelques explications sur le bricolage ci-dessus : Le dénominateur d'une fraction égyptienne est choisi entier (bien sûr) et plus grand que l'inverse de la fraction "f" (pour que l'algorithme converge). Une solution serait de prendre la troncature "int" de l'inverse de "f" et ajouter 1. Mais si l'inverse de "f" est entier, on ne doit pas ajouter 1 (sinon la suite est infinie). Alors on utilise la fonction "ceil". Donc
Enfin, "Python" ne possédant pas de boucle "do..while", il faut ajouter la dernière fraction égyptienne à la liste, pour que celle-ci soit complète.
En lançant le script ci-dessus, on apprend que formula_10.

Mathématiques avec Python et Ruby/Fractions en Ruby