22  Les f-strings

Jusqu’ici, on a affiché des valeurs avec print("x =", x) ou par concaténation. Ces approches ont leurs limites pour des affichages riches (chiffres formatés, tableaux alignés…). Les f-strings (formatted string literals), introduites en Python 3.6, sont la méthode moderne pour combiner texte et variables. Le TOSA les teste massivement dès le niveau Opérationnel.

22.1 Les trois façons de formater une chaîne

Il y a historiquement plusieurs façons de mélanger texte et variables en Python. Les f-strings sont aujourd’hui le standard — les autres sont à reconnaître (le TOSA peut les présenter) mais pas à utiliser dans du nouveau code.

Concaténation avec + (à éviter)

nom = "Alice"
age = 30
message = "Bonjour " + nom + ", vous avez " + str(age) + " ans."
print(message)
Bonjour Alice, vous avez 30 ans.

Problèmes :

  • Verbeux et difficile à lire.
  • Nécessite des str(...) pour convertir les nombres.
  • Mauvais pour les performances sur des chaînes longues.

Avec l’opérateur % (ancien style)

nom = "Alice"
age = 30
message = "Bonjour %s, vous avez %d ans." % (nom, age)
print(message)
Bonjour Alice, vous avez 30 ans.

Hérité du C. Fonctionne mais obsolète en Python moderne.

Avec la méthode .format() (Python 2.6+)

nom = "Alice"
age = 30
message = "Bonjour {}, vous avez {} ans.".format(nom, age)
print(message)
Bonjour Alice, vous avez 30 ans.

Mieux, mais toujours verbeux. Remplacé par les f-strings en Python 3.6+.

Avec les f-strings (Python 3.6+, RECOMMANDÉ)

nom = "Alice"
age = 30
message = f"Bonjour {nom}, vous avez {age} ans."
print(message)
Bonjour Alice, vous avez 30 ans.

Avantages :

  • Syntaxe lisible : les variables sont à leur place dans la chaîne.
  • Pas besoin de str(...) : la conversion est automatique.
  • Performances optimales (les f-strings sont compilées).

Le f devant la chaîne la transforme en f-string ; Python évalue ensuite tout ce qui est entre {}.

22.2 Ce qu’on peut mettre dans les accolades

À l’intérieur des {...}, on peut placer toute expression Python valide.

Une simple variable

nom = "Alice"
print(f"Bonjour {nom} !")
Bonjour Alice !

Une expression

a, b = 3, 5
print(f"{a} + {b} = {a + b}")
print(f"{a}² = {a ** 2}")
3 + 5 = 8
3² = 9

Un appel de fonction ou de méthode

nom = "alice"
print(f"Nom : {nom.upper()}")
print(f"Longueur : {len(nom)}")

import math
print(f"Racine de 2 : {math.sqrt(2)}")
Nom : ALICE
Longueur : 5
Racine de 2 : 1.4142135623730951

Un accès à une liste ou un dictionnaire

fruits = ["pomme", "banane", "cerise"]
print(f"Premier fruit : {fruits[0]}")

personne = {"nom": "Alice", "age": 30}
print(f"Nom : {personne['nom']}, Âge : {personne['age']}")
Premier fruit : pomme
Nom : Alice, Âge : 30
⚠️ Attention aux guillemets imbriqués

Si la f-string est en guillemets doubles "...", les chaînes internes doivent utiliser les apostrophes '...' (et inversement).

personne = {"nom": "Alice"}
print(f"Nom : {personne['nom']}")    # OK : apostrophes dans doubles guillemets
Nom : Alice

Sinon, vous fermeriez la f-string prématurément.

22.3 Le formatage à l’intérieur des f-strings

La vraie puissance : formater la présentation des valeurs avec {variable:spécification}.

Nombres décimaux

Spécification Effet Exemple
:.2f 2 décimales 3.14
:.0f 0 décimale (entier formaté) 3
:.5f 5 décimales 3.14159
pi = 3.14159265
print(f"π ≈ {pi:.2f}")      # 3.14
print(f"π ≈ {pi:.4f}")      # 3.1416
print(f"π ≈ {pi:.0f}")      # 3
π ≈ 3.14
π ≈ 3.1416
π ≈ 3

Entiers

Spécification Effet
:d Entier (par défaut)
:05d Entier sur 5 chiffres, préfixé de 0
:, Séparateur de milliers
n = 42
print(f"{n:05d}")           # 00042
print(f"{n:5d}")            # "   42" (sur 5 chars, aligné à droite)

grand = 1_234_567
print(f"{grand:,}")         # 1,234,567
00042
   42
1,234,567

Alignement et largeur

Spécification Effet
:>10 Aligné à droite, largeur 10
:<10 Aligné à gauche, largeur 10
:^10 Centré, largeur 10
:*^10 Centré, rempli avec *
mot = "TOSA"
print(f"[{mot:>10}]")       # droite
print(f"[{mot:<10}]")       # gauche
print(f"[{mot:^10}]")       # centré
print(f"[{mot:*^10}]")      # centré avec *
[      TOSA]
[TOSA      ]
[   TOSA   ]
[***TOSA***]

Pourcentages

:.Xp multiplie automatiquement par 100 et ajoute %.

taux = 0.175
print(f"TVA : {taux:.1%}")     # 17.5%
print(f"TVA : {taux:.0%}")     # 18%
TVA : 17.5%
TVA : 18%

Dates

Les objets datetime peuvent aussi être formatés dans une f-string (on détaille au chapitre 7) :

from datetime import datetime
maintenant = datetime(2026, 4, 22, 14, 30)
print(f"Date : {maintenant:%d/%m/%Y}")
print(f"Heure : {maintenant:%H:%M}")
Date : 22/04/2026
Heure : 14:30

22.4 Cas d’usage classique : afficher un tableau aligné

Les f-strings excellent pour produire des tableaux propres. Exemple : liste d’étudiants avec leurs notes.

etudiants = [
    ("Alice", 14),
    ("Bob", 12),
    ("Charlie", 17),
    ("Hugo", 11),
]

print(f"{'Nom':<10} {'Note':>5}")
print("-" * 16)
for nom, note in etudiants:
    print(f"{nom:<10} {note:>5}")
Nom         Note
----------------
Alice         14
Bob           12
Charlie       17
Hugo          11

Décomposition :

  • {'Nom':<10} : chaîne "Nom" alignée à gauche sur 10 caractères.
  • {'Note':>5} : chaîne "Note" alignée à droite sur 5 caractères.
  • La mise en page est propre et reproductible.

22.5 Astuces avancées

Le « self-documenting » {x=}

Depuis Python 3.8, {x=} affiche à la fois le nom et la valeur — très pratique pour le débogage.

x = 42
y = 3.14
print(f"{x=}, {y=}")
x=42, y=3.14

Sortie : x=42, y=3.14. Plus besoin d’écrire f"x={x}, y={y}".

Imbriquer des f-strings

On peut imbriquer des f-strings l’une dans l’autre (attention à la lisibilité !) :

n = 3.14159
largeur = 10
decimales = 2
print(f"{n:{largeur}.{decimales}f}")     # largeur 10, 2 décimales
      3.14

Utile quand la largeur ou le nombre de décimales est lui-même une variable.

22.6 Récapitulatif — quand utiliser quoi ?

Situation Syntaxe
Code moderne (Python 3.6+) f-string
Support Python 2 .format()
Extrait de vieux code % (à reconnaître)
Juste concaténer 2 chaînes simples str1 + str2 reste acceptable

En pratique, vous écrirez exclusivement des f-strings.

22.7 Performance : un détail intéressant

Les f-strings sont les plus rapides des 4 méthodes présentées, car Python les compile directement. Ce n’est généralement pas critique, mais c’est un bonus.

import timeit

nom = "Alice"
age = 30

t1 = timeit.timeit('"Bonjour " + nom + ", " + str(age) + " ans"',
                   globals={"nom": nom, "age": age}, number=100_000)
t2 = timeit.timeit('"Bonjour %s, %d ans" % (nom, age)',
                   globals={"nom": nom, "age": age}, number=100_000)
t3 = timeit.timeit('"Bonjour {}, {} ans".format(nom, age)',
                   globals={"nom": nom, "age": age}, number=100_000)
t4 = timeit.timeit('f"Bonjour {nom}, {age} ans"',
                   globals={"nom": nom, "age": age}, number=100_000)

print(f"Concat.   : {t1*1000:.1f} ms")
print(f"Opérateur %: {t2*1000:.1f} ms")
print(f"format()  : {t3*1000:.1f} ms")
print(f"f-string  : {t4*1000:.1f} ms")
Concat.   : 15.2 ms
Opérateur %: 16.9 ms
format()  : 20.1 ms
f-string  : 9.0 ms

🧩 Quiz 3.1 — Les f-strings

Question 1

Que s’affiche-t-il ?

x = 3.14159
print(f"{x:.2f}")
  1. 3.14159
  2. 3.14
  3. 3.1
  4. 3

b) 3.14:.2f formate un flottant avec 2 décimales.

x = 3.14159
print(f"{x:.2f}")
3.14

Question 2

Quelle syntaxe est invalide ?

  1. f"Bonjour {nom}"
  2. f"Total : {a + b}"
  3. f"Ma liste : {liste[0]}"
  4. f"Nom : {nom.upper}"

d) f"Nom : {nom.upper}" — il manque les parenthèses pour appeler la méthode : {nom.upper()}. Sans (), on référence la méthode sans l’exécuter.

nom = "alice"
print(f"Nom : {nom.upper}")      # affiche la référence de la méthode
print(f"Nom : {nom.upper()}")    # appelle la méthode
Nom : <built-in method upper of str object at 0x00000223F6F808D0>
Nom : ALICE

Question 3

Que s’affiche-t-il ?

n = 7
print(f"[{n:05d}]")
  1. [7]
  2. [ 7]
  3. [00007]
  4. [70000]

c) [00007]05d formate un entier sur 5 chiffres, préfixé de 0.

n = 7
print(f"[{n:05d}]")
[00007]

Question 4

Que s’affiche-t-il ?

mot = "TOSA"
print(f"[{mot:^10}]")
  1. [TOSA ]
  2. [ TOSA]
  3. [ TOSA ]
  4. [TOSA]

c) [ TOSA ]^10 centre sur 10 caractères. 4 caractères de TOSA + 3 espaces de chaque côté = 10.

mot = "TOSA"
print(f"[{mot:^10}]")
[   TOSA   ]

Question 5

Que s’affiche-t-il ?

taux = 0.15
print(f"{taux:.1%}")
  1. 0.15%
  2. 0.1%
  3. 15.0%
  4. 0.150%

c) 15.0%% multiplie par 100 et ajoute % automatiquement. .1 impose 1 décimale.

taux = 0.15
print(f"{taux:.1%}")
15.0%

Question 6

Quelle est l’utilité de f"{x=}" en Python 3.8+ ?

  1. Teste si x est égal à quelque chose
  2. Affiche à la fois le nom et la valeur de x
  3. Fait une affectation
  4. C’est une syntaxe invalide

b) Affiche nom et valeur — syntaxe « self-documenting » introduite en Python 3.8. Très pratique pour le débogage.

x = 42
print(f"{x=}")            # x=42

y = [1, 2, 3]
print(f"{y=}")            # y=[1, 2, 3]
x=42
y=[1, 2, 3]

Question 7

Que renvoie ce code en Python ≥ 3.6 ?

nom = "alice"
print(f"Bonjour {nom.upper()}, vous avez {2 * 15} ans")
  1. Bonjour ALICE, vous avez 30 ans
  2. Bonjour alice, vous avez 2 * 15 ans
  3. Une erreur
  4. Bonjour {nom.upper()}, vous avez {2 * 15} ans

a) Bonjour ALICE, vous avez 30 ans — les f-strings évaluent les appels de méthodes et les expressions.

nom = "alice"
print(f"Bonjour {nom.upper()}, vous avez {2 * 15} ans")
Bonjour ALICE, vous avez 30 ans

✏️ Exercice 3.1 — Tableau d’étudiants

Affichez le tableau suivant en utilisant uniquement des f-strings :

Nom           Note   Mention
------------------------------
Alice          14    Bien
Bob            12    Assez bien
Charlie        17    Très bien
Hugo           11    Passable
  • Colonne « Nom » : largeur 12, aligné à gauche.
  • Colonne « Note » : largeur 5, aligné à droite.
  • Colonne « Mention » : aligné à gauche.
etudiants = [
    ("Alice", 14, "Bien"),
    ("Bob", 12, "Assez bien"),
    ("Charlie", 17, "Très bien"),
    ("Hugo", 11, "Passable"),
]

# Afficher l'en-tête et chaque ligne avec f-strings alignées
etudiants = [
    ("Alice", 14, "Bien"),
    ("Bob", 12, "Assez bien"),
    ("Charlie", 17, "Très bien"),
    ("Hugo", 11, "Passable"),
]

print(f"{'Nom':<12} {'Note':>5}  {'Mention':<12}")
print("-" * 30)
for nom, note, mention in etudiants:
    print(f"{nom:<12} {note:>5}  {mention:<12}")
Nom           Note  Mention     
------------------------------
Alice           14  Bien        
Bob             12  Assez bien  
Charlie         17  Très bien   
Hugo            11  Passable    

✏️ Exercice 3.2 — Formatage de montants

Écrivez une fonction formater_montant(valeur, devise="€") qui renvoie le montant formaté avec 2 décimales et séparateur de milliers.

Exemple : formater_montant(1234567.89)"1,234,567.89 €".

def formater_montant(valeur, devise="€"):
    ...

print(formater_montant(1234567.89))
print(formater_montant(50, devise="$"))
def formater_montant(valeur, devise="€"):
    return f"{valeur:,.2f} {devise}"

print(formater_montant(1234567.89))
print(formater_montant(50, devise="$"))
print(formater_montant(0.5))
1,234,567.89 €
50.00 $
0.50 €

Pour obtenir "1 234 567,89 €" façon française, il faut un peu plus de travail :

def formater_montant_fr(valeur, devise="€"):
    # Format anglais par défaut
    formatted = f"{valeur:,.2f}"
    # Remplacer la virgule par un espace insécable, puis le point par la virgule
    formatted = formatted.replace(",", " ").replace(".", ",")
    return f"{formatted} {devise}"

print(formater_montant_fr(1234567.89))
1 234 567,89 €

✏️ Exercice 3.3 — Reçu de caisse

Affichez un reçu de caisse à partir d’un dictionnaire de produits :

===================================
         TICKET DE CAISSE
===================================
Pain                1.20 € × 2 =   2.40 €
Lait                0.95 € × 3 =   2.85 €
Fromage             4.50 € × 1 =   4.50 €
-----------------------------------
TOTAL                              9.75 €
===================================
panier = [
    ("Pain",     1.20, 2),
    ("Lait",     0.95, 3),
    ("Fromage",  4.50, 1),
]

# Afficher le ticket et calculer le total
panier = [
    ("Pain",     1.20, 2),
    ("Lait",     0.95, 3),
    ("Fromage",  4.50, 1),
]

print("=" * 35)
print(f"{'TICKET DE CAISSE':^35}")
print("=" * 35)

total = 0
for produit, prix, qte in panier:
    sous_total = prix * qte
    total += sous_total
    print(f"{produit:<12} {prix:>5.2f} € × {qte} = {sous_total:>6.2f} €")

print("-" * 35)
print(f"{'TOTAL':<12} {'':<20} {total:>6.2f} €")
print("=" * 35)
===================================
         TICKET DE CAISSE          
===================================
Pain          1.20 € × 2 =   2.40 €
Lait          0.95 € × 3 =   2.85 €
Fromage       4.50 € × 1 =   4.50 €
-----------------------------------
TOTAL                               9.75 €
===================================

À retenir

Points clés du chapitre
  1. f-string : préfixez avec f"..." pour évaluer les {variables} et expressions.
  2. Disponible depuis Python 3.6. C’est le standard moderne.
  3. On peut mettre toute expression dans {...} : calculs, appels de fonctions, accès à collections.
  4. Formatage : :.2f décimales, :, milliers, :>10 alignement droite, :^10 centré, :% pourcentage.
  5. Depuis Python 3.8 : {x=} affiche nom et valeur (débogage).
  6. Les f-strings sont plus rapides que .format() ou %.
  7. Pour les chaînes internes, alternez les guillemets (" avec ').

← Chapitre précédent : DocstringsChapitre suivant : Itération avancée →