Chapitre 320 minDébutant
Les bases de Python : variables, types, conditions et boucles
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- manipuler les types de base et les convertir ;
- afficher des résultats lisibles avec les f-strings ;
- écrire des conditions avec if, elif, else et match ;
- choisir entre for et while, et sortir d'une boucle avec break.
3 exercices corrigés
Les bases de Python tiennent en quatre notions : les variables qui retiennent des valeurs, les types qui disent ce que sont ces valeurs, les conditions qui choisissent quoi faire, les boucles qui répètent. Ce chapitre les présente avec la syntaxe propre à Python : l'affichage avec les f-strings, la saisie au clavier, if, match, for, while et l'indentation. Si tu découvres la programmation, le cours Algorithmique explique les mêmes notions pas à pas, en pseudo-code puis en Python.
Variables et affectation
Une variable est un nom qui désigne une valeur. On la crée en lui affectant une valeur avec = ; pas de déclaration, pas de type à écrire.
serveur = "srv-ad"
disques = 2
serveur = "srv-ad2" # la variable désigne maintenant une autre valeur
a, b = 3, 8 # deux affectations d'un coup
a, b = b, a # échange : a vaut 8, b vaut 3
TAUX_ALERTE = 80 # en majuscules : une constante, par convention
Les noms suivent la convention snake_case : minuscules et tirets bas (espace_libre, nb_postes). Ils peuvent contenir des lettres accentuées, mais évite-le : un collègue au clavier QWERTY te maudirait. Les majuscules comptent : Serveur et serveur sont deux variables différentes.
Les types de base
| Type | Ce qu'il contient | Exemples |
|---|---|---|
int | Entier, sans limite de taille | 42, -7, 2 ** 100 |
float | Nombre à virgule (flottant), avec un point | 3.5, 0.1, 1e6 |
str | Chaîne de caractères, entre " ou ' | "srv-ad", 'Chloé' |
bool | Booléen | True, False |
NoneType | L'absence de valeur | None |
La fonction type() donne le type d'une valeur ; int(), float(), str() et bool() convertissent :
>>> type(42)
<class 'int'>
>>> type(3.5)
<class 'float'>
>>> type("Sorbier")
<class 'str'>
>>> type(True)
<class 'bool'>
>>> type(None)
<class 'NoneType'>
>>> 2 ** 100
1267650600228229401496703205376
>>> 0.1 + 0.2
0.30000000000000004
>>> round(0.1 + 0.2, 2)
0.3
>>> int("42") + 1
43
>>> float("3.5")
3.5
>>> int(3.9)
3
>>> str(500) + " Go"
'500 Go'
>>> bool(0), bool(""), bool("non")
(False, False, True)
Trois remarques. Les entiers de Python n'ont pas de limite : 2 ** 100 s'affiche en entier, sans dépassement. Les flottants, eux, sont approchés : 0.1 + 0.2 ne vaut pas tout à fait 0.3, car 0,1 n'a pas d'écriture exacte en binaire (nombres à virgule en binaire) ; pour comparer deux flottants, arrondis ou compare leur écart. Enfin, int(3.9) tronque (3) au lieu d'arrondir : pour arrondir, c'est round().
Opérateurs
| Opérateur | Sens | Exemple | Résultat |
|---|---|---|---|
+ - * | Addition, soustraction, multiplication | 7 * 3 | 21 |
/ | Division, toujours flottante | 7 / 2 | 3.5 |
// | Quotient de la division entière | 7 // 2 | 3 |
% | Reste de la division entière (modulo) | 7 % 2 | 1 |
** | Puissance | 2 ** 8 | 256 |
== != | Égal, différent | 3 == 3.0 | True |
< <= > >= | Comparaisons | "abc" < "abd" | True |
and or not | Et, ou, non logiques | not (1 > 2) | True |
in | Appartenance | "ad" in "srv-ad" | True |
Python accepte les comparaisons enchaînées comme en maths : 0 <= note <= 20. Et and s'arrête dès que le résultat est connu : dans x != 0 and 10 / x > 2, la division n'est jamais faite si x vaut 0.
Afficher avec print et les f-strings
print() affiche ses arguments séparés par une espace. Pour composer un message avec des valeurs, utilise une f-string : une chaîne précédée de f, où chaque {expression} est remplacée par sa valeur. Après deux-points, un format règle l'affichage.
# disque.py : taux d'occupation d'un volume, affiché avec des f-strings
serveur = "srv-fichiers"
total_go = 500
utilise_go = 437.5
taux = utilise_go / total_go * 100
print(f"{serveur} : {utilise_go} Go utilisés sur {total_go} Go")
print(f"Occupation : {taux:.1f} %")
print(f"Libre : {total_go - utilise_go:.2f} Go")
print(f"|{serveur:<15}|{taux:>8.1f}|")
print(f"{taux=}")
srv-fichiers : 437.5 Go utilisés sur 500 Go
Occupation : 87.5 %
Libre : 62.50 Go
|srv-fichiers | 87.5|
taux=87.5
| Format | Effet | Exemple avec 87.5 |
|---|---|---|
:.1f | 1 chiffre après la virgule | 87.5 |
:.2f | 2 chiffres après la virgule | 87.50 |
:>8 | Aligné à droite sur 8 caractères | 87.5 |
:<15 | Aligné à gauche sur 15 caractères | 87.5 |
:, | Séparateur des milliers | 1,234,567 pour 1234567 |
= après le nom | Affiche le nom et la valeur, pour déboguer | taux=87.5 |
Lire une saisie avec input
input() affiche un message, attend la saisie de l'utilisateur et renvoie toujours une chaîne. Pour un nombre, convertis aussitôt :
# saisie.py : lire deux nombres au clavier
total = int(input("Taille du volume (Go) ? "))
utilise = float(input("Espace utilisé (Go) ? "))
print(f"Occupation : {utilise / total * 100:.1f} %")
Taille du volume (Go) ? 500
Espace utilisé (Go) ? 437.5
Occupation : 87.5 %
Si l'utilisateur tape autre chose qu'un nombre, la conversion échoue et le script s'arrête :
Taille du volume (Go) ? 500 Go
Traceback (most recent call last):
File "/home/etudiant/cours-python/saisie.py", line 2, in <module>
total = int(input("Taille du volume (Go) ? "))
ValueError: invalid literal for int() with base 10: '500 Go'
Le chapitre 8 montre comment intercepter cette erreur et redemander. Dans un script d'administration, on évite d'ailleurs input() : un script planifié n'a personne pour répondre. Les valeurs arrivent par la ligne de commande (chapitre 10) ou par un fichier.
Conditions : if, elif, else
# alerte.py : niveau d'alerte selon le taux d'occupation d'un disque
taux = 87.5
if taux >= 90:
niveau = "CRITIQUE"
elif taux >= 80:
niveau = "ALERTE"
else:
niveau = "OK"
print(f"Occupation {taux} % : {niveau}")
Occupation 87.5 % : ALERTE
Les conditions sont testées dans l'ordre et seule la première vraie s'exécute : 87,5 n'atteint pas 90, mais atteint 80, donc ALERTE. Écris toujours les seuils du plus exigeant au moins exigeant ; dans l'ordre inverse, taux >= 80 attraperait aussi les disques à 95 %. Les deux-points en fin de ligne et l'indentation du bloc sont obligatoires.
Pour une affectation simple selon une condition, l'expression conditionnelle tient sur une ligne : etat = "en ligne" if repond else "hors ligne".
match : choisir selon une valeur
Depuis Python 3.10, match compare une valeur à une série de motifs, comme le switch d'autres langages, en plus puissant. | sépare plusieurs valeurs possibles, _ attrape tout le reste et if ajoute une condition à un motif :
# http_codes.py : classer des codes de statut HTTP avec match
for code in [200, 201, 301, 404, 500, 418]:
match code:
case 200 | 201 | 204:
sens = "succès"
case 301 | 302 | 308:
sens = "redirection"
case 401 | 403:
sens = "accès refusé"
case 404:
sens = "ressource introuvable"
case _ if 500 <= code <= 599:
sens = "erreur du serveur"
case _:
sens = "autre code"
print(code, sens)
200 succès
201 succès
301 redirection
404 ressource introuvable
500 erreur du serveur
418 autre code
Pas besoin de break : seul le premier motif qui correspond s'exécute. Les codes HTTP sont détaillés dans le cours API REST.
Boucles for et while
La boucle for parcourt les éléments d'une séquence : une liste, une chaîne, ou les nombres produits par range(). La boucle while répète tant qu'une condition est vraie.
# boucles.py : for, range et while
for serveur in ["srv-ad", "srv-ad2", "srv-fichiers"]:
print("Contrôle de", serveur)
print(list(range(5)))
print(list(range(1, 11, 3)))
# Nombre d'adresses utilisables selon la longueur du préfixe
for prefixe in range(24, 31):
print(f"/{prefixe} : {2 ** (32 - prefixe) - 2} hôtes")
# while : en combien d'années 100 Go de données, +20 % par an, dépassent 500 Go ?
volume = 100
annees = 0
while volume <= 500:
volume = volume * 1.2
annees = annees + 1
print(f"{annees} ans ({volume:.1f} Go)")
Contrôle de srv-ad
Contrôle de srv-ad2
Contrôle de srv-fichiers
[0, 1, 2, 3, 4]
[1, 4, 7, 10]
/24 : 254 hôtes
/25 : 126 hôtes
/26 : 62 hôtes
/27 : 30 hôtes
/28 : 14 hôtes
/29 : 6 hôtes
/30 : 2 hôtes
9 ans (516.0 Go)
range(fin) produit les entiers de 0 à fin - 1 ; range(debut, fin, pas) commence à debut et avance de pas. La borne de fin est toujours exclue : range(24, 31) s'arrête à 30. La boucle des préfixes retrouve le nombre d'hôtes d'un sous-réseau, 2 puissance le nombre de bits d'hôte, moins les adresses de réseau et de diffusion (masque de sous-réseau).
Utilise for quand tu sais sur quoi tu boucles, while quand tu boucles jusqu'à ce qu'un événement arrive. Dans un while, vérifie que le corps fait avancer la condition vers faux : sinon, la boucle ne s'arrête jamais (Ctrl+C interrompt le script).
break et continue
break quitte la boucle immédiatement ; continue passe directement au tour suivant. enumerate() numérote les éléments au passage :
# break_continue.py : sortir d'une boucle, sauter un tour
codes = [200, 200, 304, 200, 500, 200]
for numero, code in enumerate(codes, start=1):
if code == 304:
continue # rien à signaler : tour suivant
if code >= 500:
print(f"Requête {numero} : erreur {code}, on arrête")
break # sortie immédiate de la boucle
print(f"Requête {numero} : {code}")
Requête 1 : 200
Requête 2 : 200
Requête 4 : 200
Requête 5 : erreur 500, on arrête
La requête 3 (code 304) est sautée par continue ; la 5 (code 500) déclenche break, et la 6 n'est jamais examinée.
L'indentation
En Python, l'indentation est la syntaxe : un bloc commence après les deux-points et regroupe les lignes indentées de la même façon. La convention (PEP 8) est de 4 espaces par niveau ; les éditeurs les insèrent quand tu appuies sur Tab. Un bloc oublié :
taux = 95
if taux >= 90:
print("Disque presque plein")
File "/home/etudiant/cours-python/indentation.py", line 3
print("Disque presque plein")
^^^^^
IndentationError: expected an indented block after 'if' statement on line 2
Python indique la ligne fautive et la cause : il attendait un bloc indenté après le if de la ligne 2. Les autres erreurs classiques : IndentationError: unexpected indent (une ligne indentée sans raison) et TabError (tabulations et espaces mélangés dans un même bloc, souvent après un copier-coller).
Exercices
Exercice 1 sur 3 Prévoir l'affichage Réussi À revoir
Sans exécuter, écris ce qu'affiche ce programme :
prix_ht = 249.9
quantite = 3
remise = quantite >= 3
total = prix_ht * quantite
if remise:
total = total * 0.9
print(f"{quantite} × {prix_ht} € HT, remise : {remise}")
print(f"Total HT : {total:.2f} €")
print(f"Total TTC : {total * 1.2:.2f} €")
Voir la réponseMasquer la réponse de l'exercice 1
3 × 249.9 € HT, remise : True
Total HT : 674.73 €
Total TTC : 809.68 €
quantite >= 3 est une comparaison : elle vaut True, rangé dans remise. 249,9 × 3 = 749,7, et 749,7 × 0,9 = 674,73. Le TTC vaut 674,73 × 1,2 = 809,676, arrondi à l'affichage à 809,68 par le format .2f.
Tu avais trouvé ?
Exercice 2 sur 3 Un mot de passe conforme Réussi À revoir
La politique de Sorbier exige au moins 12 caractères dont au moins un chiffre. Écris un script qui demande un mot de passe et affiche Conforme, Trop court : n caractères sur 12 ou Il manque un chiffre. La méthode caractere.isdigit() dit si un caractère est un chiffre. Teste avec Sorbier2026!, Entrepot71 et MotDePasseSansChiffre.
Voir la réponseMasquer la réponse de l'exercice 2
# ex_mdp.py : vérifier qu'un mot de passe fait au moins 12 caractères et contient un chiffre
mot_de_passe = input("Mot de passe à tester ? ")
contient_chiffre = False
for caractere in mot_de_passe:
if caractere.isdigit():
contient_chiffre = True
break
if len(mot_de_passe) >= 12 and contient_chiffre:
print("Conforme")
elif len(mot_de_passe) < 12:
print(f"Trop court : {len(mot_de_passe)} caractères sur 12")
else:
print("Il manque un chiffre")
Mot de passe à tester ? Sorbier2026!
Conforme
Mot de passe à tester ? Entrepot71
Trop court : 10 caractères sur 12
Mot de passe à tester ? MotDePasseSansChiffre
Il manque un chiffre
Le break arrête la recherche au premier chiffre trouvé. La longueur se teste avant le chiffre dans le elif : un mot de passe court et sans chiffre est signalé comme trop court. Une politique de mots de passe réelle se décide avec les recommandations de l'ANSSI (cours Authentification) ; ce script ne fait que la contrôler.
Tu avais trouvé ?
Exercice 3 sur 3 Combien de bits ? Réussi À revoir
Écris un script qui demande un nombre de postes et affiche le plus petit nombre de bits n tel que 2ⁿ est au moins égal à ce nombre. Teste avec 300 et avec 256. Quelle boucle choisis-tu, et pourquoi ?
Voir la réponseMasquer la réponse de l'exercice 3
On ne sait pas d'avance combien de tours faire : c'est un while.
# ex_bits.py : le plus petit nombre de bits n tel que 2**n >= postes
postes = int(input("Nombre de postes à numéroter ? "))
n = 0
while 2 ** n < postes:
n = n + 1
print(f"{n} bits suffisent : 2**{n} = {2 ** n} valeurs")
Nombre de postes à numéroter ? 300
9 bits suffisent : 2**9 = 512 valeurs
Nombre de postes à numéroter ? 256
8 bits suffisent : 2**8 = 256 valeurs
2⁸ = 256 < 300 ≤ 512 = 2⁹ : il faut 9 bits. Pour 256 postes, 8 bits suffisent tout juste : la condition 2 ** n < postes devient fausse dès que 2ⁿ égale le nombre de postes. Écrire <= au lieu de < donnerait 9 bits, un de trop : vérifie toujours le cas limite.
Tu avais trouvé ?