Style et lisibilité

Python en NSI : écrire un code lisible, spécifié et testé

Style et lisibilité · · Publié le 2026-11-10

Des rangées d'élèves tapant sur de lourdes machines à écrire dans une salle de classe de lycée, un tableau noir derrière eux
Un cours de dactylographie à l'Eastern High School de Washington. National Photo Company Collection, Bibliothèque du Congrès, domaine public.

Au lycée, Python est d'abord un outil pour apprendre l'algorithmique. Mais le programme de la spécialité numérique et sciences informatiques (NSI) va plus loin qu'« un programme qui marche » : il demande de spécifier, de documenter et de tester. Les conventions de la communauté Python, PEP 8 et PEP 257 en tête, donnent une manière simple et reconnue de répondre à ces attentes.

Ce que dit le programme officiel

Le programme de NSI de première générale, publié en annexe du Bulletin officiel spécial n° 1 du 22 janvier 2019, consacre un paragraphe au choix du langage. Il faut, dit-il, un langage « simple d'usage, interprété, concis, libre et gratuit, multiplateforme, largement répandu », riche de bibliothèques et doté d'une vaste communauté dans le monde éducatif. Et il conclut : « Au moment de la conception de ce programme, le langage choisi est Python version 3 (ou supérieure). » La phrase suivante compte autant : « L'expertise dans tel ou tel langage de programmation n'est cependant pas un objectif de formation. »

La rubrique « Langages et programmation » fixe ensuite des attentes qui dépassent la syntaxe. Son introduction pose que « l'importance de la spécification, de la documentation et des tests est à présenter », ainsi que l'intérêt de la modularisation. Le tableau des capacités attendues précise :

Le programme accorde aussi une souplesse : pour les programmes simples écrits par les élèves, « on peut se contenter d'une spécification rapide mais précise ». C'est exactement ce qu'offre une bonne docstring.

Prototyper : un nom clair et une docstring

En Python, le prototype d'une fonction, c'est sa ligne def : son nom et ses paramètres. PEP 8 demande des noms de fonctions et de variables en minuscules, les mots séparés par des tirets bas (snake_case). Le nom doit dire ce que fait la fonction : moyenne(notes) se comprend sans lire le corps, f(l) non. PEP 8 déconseille d'ailleurs expressément les noms d'une lettre l, O et I, que certaines polices confondent avec les chiffres un et zéro. Rien n'interdit d'écrire ces noms en français, comme on le fait en classe ; notre article Coder en français ou en anglais ? explique pourquoi il vaut mieux alors éviter les accents.

Juste sous la ligne def, une chaîne entre triples guillemets forme la docstring. PEP 257, la convention des docstrings, demande une première ligne courte qui résume ce que fait la fonction, puis, si nécessaire, une ligne vide et une description plus longue. C'est l'endroit naturel pour la spécification attendue par le programme :

def moyenne(notes):
    """Renvoie la moyenne d'une liste de notes non vide.

    >>> moyenne([12, 15, 9])
    12.0
    """
    assert len(notes) > 0, "la liste de notes est vide"
    return sum(notes) / len(notes)

La première ligne énonce à la fois le résultat (la postcondition : on obtient la moyenne) et la précondition (la liste ne doit pas être vide). La docstring n'est pas un simple commentaire : Python la conserve, et help(moyenne) l'affiche dans la console. C'est la même mécanique qui permet de lire la documentation des bibliothèques, l'autre capacité attendue par le programme. Notre guide (en anglais) sur les docstrings selon PEP 257 détaille les formats plus complets utilisés dans les projets professionnels.

Les préconditions : assert, utile mais pas infaillible

L'instruction assert vérifie une condition et lève une AssertionError si elle est fausse, avec le message éventuellement fourni. Appelée avec une liste vide, la fonction ci-dessus s'arrête sur AssertionError: la liste de notes est vide, ce qui est bien plus parlant qu'une division par zéro.

Il faut cependant savoir une chose, souvent ignorée : les assertions disparaissent quand Python est lancé avec l'option -O (optimisation). Nous l'avons vérifié avec Python 3.13 : avec python3 -O, le même appel produit une ZeroDivisionError, l'assertion n'ayant pas été exécutée. Les assertions servent donc à documenter et à vérifier les hypothèses pendant le développement, ce qui correspond exactement à l'usage proposé par le programme. Dans un logiciel destiné à des utilisateurs, une donnée invalide se traite plutôt avec une exception explicite (raise ValueError(...)), qui ne dépend d'aucune option.

Les jeux de tests : doctest, puis des fonctions de test

La ligne qui commence par >>> dans la docstring n'est pas décorative : c'est un exemple que le module doctest de la bibliothèque standard sait exécuter et comparer au résultat attendu. Il suffit d'ajouter en fin de fichier :

if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose=True)

Exécuté, le fichier affiche le détail de chaque exemple puis « 1 passed » et « Test passed. ». L'avantage pédagogique est double : l'exemple montre au lecteur comment appeler la fonction, et il échoue dès que le code ne fait plus ce que la documentation promet.

Pour un jeu de tests plus fourni, on écrit des fonctions de test séparées, composées d'assertions : un cas ordinaire, un cas limite (une seule note), un cas qui doit échouer. C'est là que la remarque du programme prend son sens : dix tests qui vérifient tous le même cas ordinaire ne prouvent pas grand-chose ; trois tests bien choisis, aux limites, en disent plus. Et aucun nombre de tests ne prouve qu'un programme est correct.

La mise en page : ce que vérifie un outil

Le reste de PEP 8 rend le code lisible pour le professeur qui corrige comme pour l'élève qui se relit une semaine plus tard :

Inutile d'apprendre ces règles par cœur : un vérificateur les signale. Le vérificateur de la page d'accueil fonctionne dans le navigateur, sans rien envoyer, ce qui le rend utilisable en salle informatique sans installation ; son interface est en anglais, mais les codes d'erreur (E225, W291…) sont ceux de pycodestyle, l'outil de référence. Sur une machine où l'on peut installer des paquets, flake8 ou ruff font le même travail en ligne de commande.

Une grille simple pour se relire

QuestionAttente du programmeRéponse en Python
Le nom dit-il ce que fait la fonction ?Prototyper une fonctiondef + nom en snake_case
Sait-on ce qu'il faut lui donner et ce qu'elle renvoie ?Préconditions, postconditionsDocstring (PEP 257)
Que se passe-t-il si l'entrée est invalide ?Garantir les préconditionsassert, ou une exception
Comment sait-on qu'elle marche ?Utiliser des jeux de testsdoctest, fonctions de test
Le code est-il agréable à relire ?Documentation, modularisationPEP 8, vérifié par un outil

Ces habitudes ne sont pas réservées au lycée : ce sont celles que l'on attend d'un code publié, y compris dans le secteur public, comme le montre notre article sur la publication de code Python par les organismes publics.

Sources