Sylvie Combes tient le fichier des adhérents d'une école de musique associative à Nancy. En juin, huit lignes lui ont sorti la liste des élèves par ordre alphabétique, pour le programme du concert. Le programme est parti chez l'imprimeur avec Élise Vaillant et Émile Roy tout à la fin, après Zoé Ferrand.
Ce programme n'a pas de bogue. Il fait exactement ce qui est écrit : il compare des chaînes de caractères, et la comparaison porte sur les codes, pas sur l'alphabet. Le É majuscule porte le numéro 201 et le Z le numéro 90, donc le É passe après. Aucun cours de Python ne contient cette phrase, parce qu'aucune liste de noms anglais ne la produit.
Ce qui manquait à Sylvie n'était pas de la syntaxe. C'était un prix, et l'idée qu'un prix a été fixé par quelqu'un avant elle. Cette idée ne tient à aucun langage, et c'est la raison pour laquelle elle vit ici plutôt que dans les langages de programmation.
Ce qui reste quand on change de langage
Les huit rubriques rangées sous ce sujet répondent chacune à une version de la même question : ce que coûte une opération quand il y en a davantage, et ce qui reste vrai quand la syntaxe change. Les structures de données sont un pari sur l'opération que vous ferez le plus souvent. Les algorithmes sont des façons nommées de ne pas payer un prix que quelqu'un a déjà su éviter. Les patrons de conception font le même arbitrage à la taille d'un programme plutôt qu'à celle d'une boucle. Même le code lisible est un prix : celui du deuxième lecteur, qui est vous dans huit mois.
Aucune des huit n'est la première et aucune ne se prend seule. Sylvie n'avait besoin ni du mot collation ni du nom d'un algorithme de tri. Elle avait besoin de savoir qu'un tri compare, que comparer se règle quelque part, et que le réglage livré n'est pas le français.
Trois prix, avant d'ouvrir une rubrique
Le premier est celui qui a exilé Émile en fin de programme. Le pliage qui le corrige tient dans la bibliothèque standard et ne demande rien à installer.
import unicodedatanoms = ["Ahmed Belkacem", "Zoé Ferrand", "Élise Vaillant", "Émile Roy", "Nour Haddad"]def cle(n):return unicodedata.normalize("NFD", n).encode("ascii", "ignore").decode().lower()print(sorted(noms))print(sorted(noms, key=cle))
La cinquième ligne affiche Ahmed Belkacem, Nour Haddad, Zoé Ferrand, Élise Vaillant, Émile Roy. La sixième affiche l'ordre du programme de concert. La forme NFD sépare la lettre accentuée en une lettre et un accent posé à part, l'encodage en ASCII jette ce second morceau, et le tri retombe sur l'alphabet. Rien là-dedans n'est propre à Python : PHP, JavaScript et Java trient tous les trois par code, et tous les trois demandent qu'on le leur dise.
Le deuxième prix décide de la forme, et il se mesure. Chercher un identifiant parmi 20 000 adhérents oblige à parcourir la liste jusqu'à le trouver ; le chercher dans un ensemble demande une seule opération. Mesuré le 8 septembre 2026 sur un portable ordinaire : deux mille recherches du dernier élément prennent 0,39 seconde sur la liste et 0,00007 seconde sur l'ensemble, environ cinq mille cinq cents fois moins. Un ensemble répond en temps constant, une liste se parcourt jusqu'au bout, et l'écart ne se voit pas sur cinq noms.
La faute qui produit ce genre d'écart se reconnaît en lisant : une boucle dans une boucle sur la même liste, c'est n au carré, donc mille adhérents font un million de comparaisons, et doubler l'effectif quadruple le travail au lieu de le doubler. L'utile n'est pas de calculer le chiffre. C'est de voir le deuxième for indenté sous le premier et de se demander ce que contiendra la liste dans un an.
Le troisième prix ne concerne pas la vitesse et il produit les bogues les plus étranges. Quand Sylvie a voulu une copie de travail pour cocher les présents, elle a écrit presents = adherents, puis a constaté qu'enlever un nom de l'une l'enlevait de l'autre. Deux noms sur la même liste sont une seule liste. Un nom est une étiquette posée sur un objet, pas une boîte qui en contient une copie, et presents = list(adherents) est la ligne qui fait exister la seconde. C'est vrai de presque tous les langages, et chacun l'écrit autrement.
Un montant en euros n'est pas un nombre à virgule
Le fichier des cotisations est exporté par un tableur français, donc les montants y sont écrits 19,99. float("19,99") lève une ValueError, et c'est la bonne nouvelle : la faute est bruyante. La mauvaise arrive avec float("19.99"), qui passe sans rien dire. Un flottant ne sait pas écrire un dixième : 0.1 + 0.2 vaut 0.30000000000000004, sur toutes les machines et dans tous les langages qui suivent la même norme.
La règle qui tient est de compter en centimes. Un prix en euros se calcule en centimes, avec des entiers, et ne redevient un euro qu'à l'affichage. La cotisation de 19,99 € devient 1999, la part de TVA à 20 % se calcule sur cet entier, et la ligne du bordereau est juste au centime. Une association qui arrondit trois cents fois par an s'en aperçoit le jour où le trésorier ne retrouve pas son total, c'est-à-dire un an trop tard.
L'ordre
Quatre marches, et la troisième est celle qu'on attend au lieu d'aller la chercher
Un lecteur français est déjà sur la première sans le savoir, et cale entre la deuxième et la troisième pendant des années.
- 01Reconnaître le mot déjà eu en coursTable de hachage, complexité, tableau. Le vocabulaire est acquis, et il ne figure nulle part dans le code.
- 02Le retrouver sous son nom anglaisdict, list, str, heap. Une demi-heure de travail, et la documentation s'ouvre enfin.
- 03Être surpris par un chiffre, une foisRegarder vingt mille comparaisons se traîner là où une seule opération suffisait. Rien au-dessus ne tient sans cela.
- 04Écrire pour le deuxième lecteurLes habitudes ne se comprennent que le jour où l'on rouvre son propre fichier huit mois plus tard.
Elle ne dit rien de la durée. La deuxième marche prend une demi-heure, la troisième ne se franchit couramment pas avant deux ans, et c'est tout l'argument pour aller la chercher plutôt que de l'attendre.
Le mot était en français, le prix ne l'était pas
Le lecteur français arrive ici avec le vocabulaire et sans les prix, et c'est une situation que la page anglaise n'a pas à décrire. La spécialité Numérique et sciences informatiques existe au lycée depuis la rentrée 2019 en première et 2020 en terminale, et elle est bâtie sur quatre concepts : les données, les algorithmes, les langages et les machines. Avant elle il y a SNT en seconde, à côté le BTS SIO et les classes préparatoires. Beaucoup de gens qui cherchent les bases de la programmation ont donc déjà eu ce chapitre, en français, et noté.
Le blocage vient de là, et il ne ressemble pas à un manque de capacité. Il ressemble à une permission qu'on ne se donne pas : reprendre un chapitre déjà validé passe pour un retour en arrière. Ce n'en est pas un, parce que ce qui a été validé était le mot et non le prix. On peut réciter la définition d'une table de hachage sans avoir jamais regardé une boucle imbriquée prendre quatre minutes.
La seconde moitié est mécanique et se règle vite. Ce qui a été appris en français porte un autre nom dans le code, et le mot français ne se trouve dans aucune documentation. Un tableau est une list, une chaîne de caractères une str, une table de hachage un dict, une file une queue, un tas un heap. Chercher tableau associatif dans la documentation d'un paquet ne rend rien, chercher dict rend la page. Les briques de base tiennent les deux colonnes, langage par langage.
L'ordre qui tient, et ce que coûte l'ordre inverse
Presque personne n'arrive ici dans l'ordre, parce que le cours par lequel on commence va droit aux constructions et ne parle jamais de prix. Pris à l'envers, l'échec est précis : les noms avant les prix. Quelqu'un qui sait réciter ce qu'est une table de hachage et n'a jamais vu vingt mille éléments se traîner choisira mal sous pression, sans savoir pourquoi son programme est lent. Les noms s'acquièrent tard sans dommage. L'instinct, non, et il se construit en étant surpris par un chiffre au moins une fois.
L'autre ordre qui casse concerne les patrons, lus avant d'avoir rencontré deux fois le même problème : un patron appris tôt est une réponse à laquelle il manque sa panne, et il produit six fichiers là où un seul suffisait. Le débogage ferme la marche dans les sommaires et ouvre la marche dans la vraie vie, le jour où l'une des sept autres rubriques a été devinée plutôt que sue.
Ce qu'on ouvre en 2026
Pour les questions de prix, timeit est dans la bibliothèque standard de Python et tranche en une dizaine de secondes entre deux versions d'une boucle. Il a remplacé l'habitude de mettre un chronomètre autour du script entier, qui mesure aussi le démarrage de l'interpréteur. La ligne python3 -m timeit -s "d = set(range(20000))" "19999 in d" se tape depuis n'importe quel terminal, en France comme ailleurs, sans compte et sans abonnement.
Pour les questions d'accents, unicodedata est dans la même bibliothèque et remplace la table de correspondance que chacun réécrit une fois dans sa vie, avec les mêmes oublis : le ÿ de L'Haÿ-les-Roses, la cédille, la ligature œ. Quand le tri doit suivre les règles françaises plutôt qu'un pliage, locale.strxfrm le fait, à condition que la locale française soit installée sur la machine. Elle ne l'est pas sur un serveur nu, et c'est une des surprises que réserve la mise en production.
Pour les questions d'arrêt, pdb arrive avec Python et reprend le travail du print ajouté puis relancé. La ligne python3 -m pdb -c continue programme.py dépose au moment de la panne avec toutes les valeurs encore en mémoire, ce qu'un print ne rend pas. Un assistant dans l'éditeur écrira la version pliée du tri de Sylvie tout de suite et correctement, parce que c'est une forme courante ; il ne dira pas pourquoi elle était nécessaire, et c'est cette phrase-là qui manquait au programme du concert.
Reste la question que Sylvie s'est posée ensuite : à partir de combien d'adhérents un fichier cesse d'être un fichier. La réponse se trouve dans les bases de données, où le tri, la casse et les accents redeviennent un réglage, posé cette fois par le serveur et non par elle.