Faragiri
Français

Apprendre les bases de Python Python

Huit tournures montrées contre la version qu'on écrit en premier, dont l'affichage de débogage qui imprime sa propre expression et le tri à deux clés.

5Sections
4Min de lecture
4Profondeur

Les trois mêmes lignes, deux fois

La version qui marche, et la version qui n'a nulle part où cacher un bug

Les deux colonnes s'exécutent et donnent la même réponse. La colonne de droite ne contient aucun index, et c'est exactement là que se trouve la différence.

Écrit depuis un autre langageIndex, compteurs et une liste temporaire
Écrit en PythonDécompression, et la boucle annonce elle-même sa forme
Lire trois champsr[0], r[1], r[2]for ref, stock, prix in lignes
Vouloir la positioni = 0, puis i += 1enumerate(lignes, start=1)
Associer deux listesUne boucle sur range(len(refs))dict(zip(refs, prix))
Filtrer vers un dictionnaireUn dictionnaire vide et un if dans une boucle{r: s for r, s, _ in lignes if s}
Un affichage de débogageprint("total", total)f"{total=}"

Le côté droit est marqué parce que sur ces cinq lignes il existe une bonne réponse. Ce n'est pas vrai de toutes les paires dans ce langage, et une figure qui marque un gagnant prend position plutôt que de comparer.

La syntaxe de Python est petite, ses tournures ne le sont pas, et l'écart entre du Python qui marche et du Python qui coule se voit sur huit d'entre elles environ. Prenez un stock de fromages, trois lignes ('FR-12', 5, 18) et deux comme elle, et la différence apparaît à chaque ligne.

  • Décompresser dans l'en-tête de boucle : for ref, stock, prix in lignes plutôt que r[0], r[1], r[2]
  • enumerate(lignes, start=1) quand la position compte, ce qui donne (1, 'FR-12') sans compteur à tenir
  • dict(zip(refs, prix)) construit {'FR-12': 18, 'FR-13': 24, 'FR-14': 15} en une ligne
  • first, *reste = refs répond 'FR-12' et ['FR-13', 'FR-14']
  • refs[::-1] inverse sans toucher à l'original
  • Une compréhension de dictionnaire avec filtre : {r: s for r, s, _ in lignes if s} retire la référence en rupture et répond {'FR-12': 5, 'FR-13': 2}

Deux idiomes plus récents que la plupart des tutoriels

Une f-string qui se termine par un signe égal imprime l'expression en plus de sa valeur : f"{total=}" donne total=138 pour le stock de Karim Belhadj, dont la fromagerie est à Rennes. C'est un affichage de débogage qui ne peut pas s'éloigner du nom qu'il rapporte, et il est arrivé avec Python 3.8. Le formatage se combine : f"{total:,} grammes sur {len(lignes)} lignes" pose les séparateurs de milliers, et f"{total/len(lignes):.1f} moyenne" répond 46.0.

Le compromis du walrus, et où il ne sert à rien

L'opérateur morse affecte une valeur à l'intérieur d'une condition, donc elle est calculée une fois et gardée : if (virgule := ligne.find(",")) != -1: puis ligne[:virgule]. Sans lui, la recherche s'exécute deux fois ou un nom est lié une ligne plus haut et vit plus longtemps qu'il ne devrait. Il vaut exactement ce prix et pas plus, ce qui explique la règle de ne s'en servir que là où l'alternative est un appel répété.

La clé de tri qui porte deux sens à la fois

Trier sur deux critères, dont l'un est décroissant, ne demande pas de fonction de comparaison ni deux passes. Il suffit de nier la clé numérique : sorted(lignes, key=lambda r: (-r[1], r[0])) met le stock le plus haut en premier et départage par ordre alphabétique, donc FR-12 avec 5 fromages précède FR-13 avec 2. La clé est comparée de gauche à droite, et c'est toute la règle.

Cette astuce ne marche que sur des nombres. Pour une clé texte décroissante, la réponse tient en deux tris dans l'ordre opposé, en s'appuyant sur la stabilité du tri, ce qui est une des rares façons de faire, et la raison pour laquelle chaque langage en a déjà choisi une.

Ce qu'on installe en 2026

Ruff porte l'essentiel de tout ceci mécaniquement, gratuit et open source, et il est en 2026 le vérificateur par défaut des projets Python. Ses règles nomment la boucle qui aurait dû être une compréhension, le range(len(x)) qui aurait dû être un enumerate, et l'index manuel qui aurait dû être une décompression. Il a remplacé le fait d'apprendre ces tournures une à une en revue de code, ce qui marche et prend environ deux ans.

Python 3.14 est la version sur laquelle rester, gratuite, et ses messages d'erreur sont la vraie raison plutôt qu'une quelconque promesse de vitesse. Il a remplacé Python 3.13, et pour les tournures ci-dessus la version qui compte est 3.8 pour la f-string à signe égal et le walrus, ce qui est assez ancien pour que tout ce qui tourne encore sans elles soit une contrainte à nommer plutôt qu'une préférence.

Le blocage : écrire une autre langue en Python

Le blocage, c'est d'arriver d'un autre langage et d'écrire ce langage en Python, ce qui fonctionne parfaitement et se fait qualifier de pas pythonique en revue sans que personne n'explique le coût. Le coût est réel : for i in range(len(lignes)) suivi de lignes[i][0] est trois occasions de se tromper d'index sur chaque ligne, et la version décompressée n'en a aucune.

Le contrôle qui raccourcit les deux ans : chaque fois qu'un index apparaît deux fois sur une même ligne, il existe une tournure pour l'éviter. Chaque fois qu'une liste temporaire est construite pour être ensuite parcourue, il existe une compréhension ou un générateur. Ce que ces tournures remplacent en pratique tient dans la bibliothèque standard, ce qui évite d'ajouter une dépendance, et l'endroit où le stock lui-même vit sans se mélanger à celui d'un autre projet est les paquets et les environnements. Ce que la valeur décompressée était avant d'être une tournure Python se trouve dans les variables et les types.

À côté

Au-dessus