Et si une fonction s'appelait elle-meme ?#
Une fonction peut s'appeler elle-meme. Ce n'est pas une erreur : c'est la recursion, une technique aussi elegante qu'un miroir face a un autre miroir. L'exemple classique : calculer une factorielle.
def factorielle(nombre): if nombre <= 1: return 1 return nombre * factorielle(nombre - 1) # factorielle(5) # = 5 * factorielle(4) # = 5 * 4 * factorielle(3) # = 5 * 4 * 3 * factorielle(2) # = 5 * 4 * 3 * 2 * factorielle(1) # = 5 * 4 * 3 * 2 * 1 = 120La fonction s'appelle jusqu'au cas de base (nombre <= 1) qui arrete la descente. Sans cas de base, la recursion ne s'arrete jamais.
L'arbre fractal - clin d'oeil a la Mission Foret
La recursion brille quand on dessine des fractales. Un arbre : on dessine un tronc, puis on appelle deux fois la meme fonction pour deux branches plus courtes et legerement tournees, qui appellent elles-memes deux sous-branches, etc. C'est exactement comme un vrai arbre qui se ramifie. Essaie d'augmenter la profondeur :
Arbre fractal recursif
A profondeur 1, il n'y a qu'un tronc. A profondeur 12, des centaines de branches - toutes tracees par la meme petite fonction appelee en cascade.
En Python, le code de cet arbre ressemble a ceci :
import turtle import math def dessinerBranche(crayon, longueur, angle, profondeur): if profondeur == 0: return crayon.forward(longueur) crayon.left(angle) dessinerBranche(crayon, longueur * 0.72, angle, profondeur - 1) crayon.right(angle * 2) dessinerBranche(crayon, longueur * 0.72, angle, profondeur - 1) crayon.left(angle) crayon.backward(longueur)La pile d'appels et le RecursionError
Chaque fois qu'une fonction s'appelle elle-meme, Python met en attente l'appel precedent (comme une assiette posee sur une pile). Quand on revient, on depile. Si la recursion ne s'arrete jamais - cas de base oublie - la pile d'assiettes tombe : Python leve un RecursionError: maximum recursion depth exceeded.
La limite existe pour proteger la memoire. On peut la modifier avec sys.setrecursionlimit(), mais mieux vaut revoir son algorithme.
Les sous-programmes, plus vieux que vos ordinateurs#
L'idee d'ecrire une sequence d'instructions une seule fois et de la reutiliser est aussi vieille que les premiers ordinateurs electroniques.
A Cambridge, sur l'ordinateur EDSAC, entre 1949 et 1951, Maurice Wilkes, David Wheeler et Stanley Gill mettent au point les premieres sous-routines reutilisables. Wheeler invente une astuce de saut qui permet de sauter vers une sous-routine et d'en revenir : le « Wheeler jump », ancetre direct de nos appels de fonctions. En 1951, les trois publient The Preparation of Programs for an Electronic Digital Computer - le premier livre de programmation de l'histoire. Chaque sous-routine etait conservee sur une carte perforee separee et pouvait etre inseree dans n'importe quel programme.
Presque au meme moment, en 1952, Grace Hopper cree le compilateur A-0 pour l'ordinateur UNIVAC. Ce compilateur peut assembler des routines reutilisables stockees sur bande magnetique et les combiner automatiquement en un programme complet. C'est l'une des racines directes de l'idee « ecrire une fois, reutiliser partout ».
Grace Hopper - visionnaire des langages lisibles
Grace Murray Hopper (1906-1992) etait mathematicienne, informaticienne et contre-amirale de la marine americaine. Elle a popularise le terme « bug » apres qu'une vraie mite s'est coincee dans un relais de l'ordinateur Mark II en 1947 - l'incident est consigne dans le journal de bord avec l'insecte colle au ruban.
Mais sa contribution la plus profonde est d'avoir cru qu'on pouvait ecrire des programmes dans un langage proche de l'anglais. Ses travaux ont mene directement au langage COBOL (1959), longtemps le langage le plus utilise au monde pour les applications bancaires et d'entreprises - et qui tourne encore aujourd'hui dans de nombreux systemes financiers.
"A ship in port is safe, but that's not what ships are built for." - Grace Hopper
| Annee | Qui | Quoi |
|---|---|---|
| 1949-1951 | Wilkes, Wheeler, Gill (Cambridge) | Premieres sous-routines reusables sur EDSAC ; premier livre de programmation (1951) |
| 1952 | Grace Hopper (USA) | Compilateur A-0 : assemblage automatique de routines stockees sur bande |
| 1959 | Comite CODASYL (Hopper, contributrice majeure) | Naissance de COBOL, premier langage lisible oriente metier |
DRY : ne te repete jamais#
En 1999, Andrew Hunt et David Thomas publient The Pragmatic Programmer et y formulent le principe DRY : Don't Repeat Yourself (ne te repete pas). L'idee en une phrase :
Principe DRY
"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."
Chaque savoir doit avoir une seule source dans le code. Pas deux. Pas trois.
Le copier-coller est une usine a bugs. Quand le meme bloc de code existe a trois endroits et qu'on decouvre une erreur, on la corrige... mais on oublie les deux autres copies. Le bug vit encore, cache. Avec une fonction, il n'y a qu'un seul endroit a corriger.
Voici un exemple concret - calcul du prix avec taxes pour plusieurs produits :
AVANT - code duplique (danger)
prixPomme = 1.50 taxePomme = prixPomme * 0.15 totalPomme = prixPomme + taxePomme print(totalPomme) prixPain = 2.75 taxePain = prixPain * 0.15 totalPain = prixPain + taxePain print(totalPain) prixLait = 3.20 taxeLait = prixLait * 0.15 totalLait = prixLait + taxeLait print(totalLait) # Si le taux passe a 0.14975 ? # 3 endroits a corriger... # Et si on en oublie un ?APRES - DRY avec une fonction
TAUX_TAXE = 0.15 def calculerPrixAvecTaxe(prix): taxe = prix * TAUX_TAXE return prix + taxe print(calculerPrixAvecTaxe(1.50)) print(calculerPrixAvecTaxe(2.75)) print(calculerPrixAvecTaxe(3.20)) # Si le taux change : 1 seul endroit. # Si le calcul change : 1 seul endroit. # Zero risque d'oubli.Le principe DRY va plus loin que les fonctions : il s'applique aussi aux constantes, aux fichiers de configuration, aux bases de donnees. Mais dans un cours de programmation, la fonction est l'outil numero un pour appliquer DRY. Chaque fois que tu copies un bloc de code, demande-toi : est-ce qu'une fonction ferait mieux le travail ?
Essaie : que se passe-t-il si on change le taux ?
Avec une fonction, changer le taux met a jour tous les produits d'un coup. Sans fonction, tu devrais chercher et corriger chaque copie manuellement.