Fibonacci en Python - Boucle, générateur ou récursion?

Noël Besnard .

26 mars 2026

Code Rust implémentant la suite de Fibonacci avec `num_bigint`. Le code utilise une approche récursive pour calculer les nombres de Fibonacci.

La suite de Fibonacci est un petit exercice qui en dit beaucoup sur la façon d’écrire du Python propre: boucle, récursion, générateur, cache et gestion des limites réelles du code. Ici, je vais montrer les approches utiles pour générer la suite de Fibonacci en Python, expliquer quand chacune est pertinente et éviter les pièges classiques. Si vous voulez aller au-delà d’un simple exemple de manuel, c’est exactement le bon terrain.

Les points à retenir avant d’écrire le code

  • Pour produire une suite finie, la boucle reste la solution la plus lisible et la plus robuste.
  • Pour consommer les valeurs une par une, un générateur est plus propre qu’une liste complète.
  • La récursion pure est élégante mais devient vite trop coûteuse.
  • Avec `functools.lru_cache`, la récursion devient acceptable pour des tailles modestes.
  • En Python, la taille des entiers augmente vite, donc le coût réel n’est pas seulement algorithmique.

Pourquoi la suite de Fibonacci reste un bon exercice Python

J’aime cet exemple parce qu’il révèle vite deux choses: la capacité à écrire une logique simple et claire, et la discipline nécessaire pour ne pas surcompliquer un problème qui tient en quelques lignes. Fibonacci sert souvent de test de lecture du code, pas seulement de test de syntaxe.

Ce n’est pas un problème théorique. Dès qu’on choisit entre une liste, un flux de valeurs ou une fonction qui ne renvoie qu’un terme, on touche à des questions très concrètes: mémoire, lisibilité et coût algorithmique. C’est précisément ce qui permet de choisir ensuite entre une liste, un générateur ou une version récursive.

Arbre de récursion pour la suite de Fibonacci en Python. `fib(7)` donne 13.

La version la plus lisible avec une boucle

Je pars ici sur la convention la plus courante dans un code d’exemple: 0, 1, 1, 2, 3, 5.... Si votre projet démarre à 1, 1, adaptez simplement les valeurs initiales. Je préfère cette version quand je veux une suite finie prête à être affichée, testée ou envoyée vers une autre fonction.

def suite_fibonacci(n):
    if n <= 0:
        return []
    if n == 1:
        return [0]

    suite = [0, 1]
    while len(suite) < n:
        suite.append(suite[-1] + suite[-2])

    return suite

print(suite_fibonacci(10))

Cette forme est facile à relire et assez robuste pour un débutant comme pour un code de production. Je n’utilise pas de compréhension de liste ici: la dépendance au terme précédent mérite un état explicite, pas une astuce compacte qui brouille la lecture. Quand on n’a pas besoin de tout conserver, le générateur devient alors plus intéressant.

Générer les termes à la volée avec un générateur

Un générateur est utile quand on veut produire les valeurs à la demande. On ne fabrique pas toute la liste d’un coup: chaque appel à `yield` renvoie un terme, puis la fonction reprend là où elle s’était arrêtée. C’est plus naturel pour un pipeline de données, un affichage progressif ou un traitement qui s’arrête avant le n-ième terme.

from itertools import islice

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

print(list(islice(fibonacci(), 10)))

Je choisis cette approche quand je veux consommer la suite sans l’immobiliser en mémoire. Elle est particulièrement propre dans un script qui alimente un autre traitement, parce qu’elle garde le flux de valeurs ouvert au lieu de tout matérialiser d’un coup. Si votre but est seulement d’obtenir un terme précis, la récursion avec cache peut encore avoir du sens, à condition de la cadrer.

Récursion et mémoïsation quand vous voulez un exemple plus sophistiqué

La récursion pure est séduisante, mais je la réserve surtout à l’explication pédagogique. Sans mémoïsation, elle recalcule les mêmes sous-problèmes des dizaines de fois et devient vite disproportionnée. Avec un cache, elle redevient utilisable pour des tailles modestes, même si elle reste moins directe qu’une boucle pour produire toute la suite.

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

def suite_fibonacci(n):
    return [fib(i) for i in range(n)]

print(suite_fibonacci(10))

Cette version a un intérêt précis: elle illustre bien la mémoïsation, c’est-à-dire le fait de mémoriser les résultats déjà calculés pour éviter les doublons. Sur un Python récent, `functools.cache` peut aussi faire le travail si vous n’avez pas besoin d’une limite de taille. Pour produire toute la suite, je garde toutefois une préférence nette pour la boucle ou le générateur.

Même avec ces trois formes, la vraie question reste le coût réel selon l’usage. C’est ce que je compare juste après.

Comparer les approches sans se tromper sur le coût

Le choix n’est pas seulement stylistique. En Python, les entiers grandissent sans limite pratique, mais leur addition coûte de plus en plus cher quand les termes deviennent énormes. Sur dix ou vingt valeurs, on ne voit presque rien; sur des indices élevés, c’est la taille des nombres qui finit par peser autant que l’algorithme. C’est pour cela que je déconseille la formule fermée basée sur les flottants pour du code exact: elle semble élégante, puis elle finit par trahir la précision.

Approche Temps Mémoire Forces Limites
Boucle O(n) O(n) Lisible, simple à déboguer, bon choix par défaut Stocke toute la liste si vous la renvoyez telle quelle
Générateur O(n) O(1) Idéal pour traiter les valeurs une par une Moins pratique si vous voulez réutiliser toute la suite plusieurs fois
Récursion pure O(phi^n) O(n) Bonne démonstration pédagogique Trop lente dès que n grandit
Récursion avec cache O(n) O(n) Utile pour illustrer la mémoïsation ou calculer un terme isolé Moins directe qu’une boucle pour produire une suite complète

Ce tableau résume bien mon arbitrage: si je veux une séquence concrète, je prends la boucle; si je veux un flux, je prends le générateur; si je veux expliquer le cache, je prends la récursion mémoïsée. À partir de là, le bon choix dépend moins de la théorie que du contexte du script.

Ce que je retiendrais avant de l’intégrer à un vrai script

Avant de reprendre ce code dans un projet, je vérifie toujours trois choses: la convention de départ, le mode de consommation des valeurs et le volume réel de données à produire. Une suite qui sert à afficher dix termes n’a pas les mêmes exigences qu’un traitement qui alimente une API, un notebook ou un job batch.

  • Si vous voulez une suite finie pour l’affichage ou les tests, la boucle reste la meilleure base.
  • Si vous devez chaîner des opérations sans tout stocker, le générateur est plus naturel.
  • Si vous avez besoin du n-ième terme plusieurs fois, le cache devient intéressant.
  • Si vous poussez n très haut, regardez les méthodes logarithmiques comme le fast doubling plutôt que d’insister avec une version pédagogique.

En pratique, je garde trois réflexes: une convention de départ explicite, un choix adapté à la quantité de données, et un œil sur la mémoire si la suite sort d’un simple exercice. C’est ce qui transforme un exemple Fibonacci en code Python vraiment utile, pas seulement en démonstration correcte.

Questions fréquentes

Elle révèle la capacité à écrire une logique simple et claire, et la discipline de ne pas surcompliquer un problème. Elle touche à des questions concrètes de mémoire, lisibilité et coût algorithmique, permettant de choisir entre liste, générateur ou récursion.
La boucle est idéale pour produire une suite finie, prête à être affichée, testée ou passée à une autre fonction. C'est la solution la plus lisible et robuste pour un code de production ou un débutant.
Un générateur permet de produire les valeurs à la demande, sans stocker toute la liste en mémoire. C'est parfait pour un pipeline de données, un affichage progressif ou un traitement qui s'arrête avant le n-ième terme.
La récursion pure est élégante mais très coûteuse sans optimisation. Avec un cache (`functools.lru_cache`), elle devient utilisable pour des tailles modestes et est excellente pour illustrer la mémoïsation, bien que moins directe qu'une boucle pour une suite complète.
Le choix dépend de l'usage : boucle pour une suite finie et lisible, générateur pour un flux de valeurs à la demande, et récursion avec cache pour un terme isolé ou l'illustration de la mémoïsation. Considérez la mémoire et le coût réel des grands nombres.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

implémentation fibonacci python fibonacci python suite de fibonacci python boucle générer suite fibonacci python fibonacci python récursion cache optimisation fibonacci python
Autor Noël Besnard
Noël Besnard
Je suis Noël Besnard, un analyste de l'industrie passionné par les domaines de la technologie, notamment le web, l'intelligence artificielle, les réseaux et la sécurité. Avec plus de dix ans d'expérience dans l'analyse des tendances du marché technologique, j'ai acquis une expertise approfondie qui me permet d'explorer les innovations et les défis auxquels notre monde numérique est confronté. Mon approche consiste à simplifier des données complexes et à fournir une analyse objective, ce qui me permet de rendre les sujets techniques accessibles à tous. Je m'engage à offrir des informations précises et à jour, en vérifiant rigoureusement les faits pour garantir la fiabilité de chaque article que je publie. Mon objectif est d'aider les lecteurs à naviguer dans cet univers en constante évolution, en leur fournissant les outils nécessaires pour comprendre les enjeux technologiques contemporains.

Commentaires (0)

Ajouter un commentaire