ര# 🐍 Cours Complet de Python — De Zéro à Scripteur Autonome
Auteur : GitHub Copilot
Public visé : Débutants complets qui souhaitent apprendre Python pour scripter, automatiser des tâches, et poser des bases solides en programmation.
Niveau : Débutant à Intermédiaire
Durée estimée : 30 à 60 heures de pratique
📑 Table des matières ¶
- Introduction à Python
- Installation et configuration de l'environnement
- Premier programme et syntaxe générale
- Variables et types de données
- Opérateurs
- Les chaînes de caractères en profondeur
- Les structures conditionnelles
- Les boucles
- Les fonctions
- Les collections (listes, tuples, dictionnaires, ensembles)
- La compréhension de listes et expressions génératrices
- Les modules et les packages
- La gestion des fichiers
- La gestion des exceptions
- La programmation orientée objet (POO)
- Les itérateurs et les générateurs
- Les décorateurs
- Le scripting (arguments, environnement, exécution)
- Les expressions régulières
- Les bonnes pratiques (PEP 8, virtualenv, pip, typage)
- Mini‑projets de fin de cours
1. 🎯 Introduction à Python ¶
1.1 Qu'est‑ce que Python ? ¶
Python est un langage de programmation interprété, multi‑paradigme (orienté objet,
procédural, fonctionnel), typé dynamiquement et fortement typé. Il a été créé
par Guido van Rossum en 1991. Son nom vient de la troupe humoristique britannique
Monty Python, et non du serpent.
Aujourd'hui, Python est l'un des langages les plus utilisés dans le monde, notamment dans :
- L'automatisation et le scripting (DevOps, sysadmin)
- Le web (Django, Flask, FastAPI)
- La data science et le machine learning (NumPy, Pandas, scikit‑learn, PyTorch)
- L'intelligence artificielle
- Les scripts ponctuels (traitement de fichiers, scraping, etc.)
- L'enseignement de la programmation
1.2 Pourquoi choisir Python ? ¶
- Lisibilité : la syntaxe est proche de l'anglais, l'indentation est obligatoire,
ce qui force un code propre. - Productivité : on peut écrire en quelques lignes ce qui prendrait des dizaines
de lignes en C ou en Java. - Communauté : énorme écosystème de bibliothèques (PyPI compte plus de 500 000 paquets).
- Multi‑plateforme : Windows, macOS, Linux, et même certains microcontrôleurs
(MicroPython, CircuitPython). - Open Source : gratuit et libre.
1.3 Python 2 vs Python 3 ¶
Python 2 n'est plus maintenu depuis le 1er janvier 2020. Tout au long de ce cours,
nous utiliserons Python 3 (à partir de la version 3.10, mais 3.8+ devrait suffire
pour la plupart des exemples).
1.4 Compilé vs interprété ¶
Python est interprété : votre code source .py est lu ligne par ligne par
l'interpréteur Python (souvent appelé CPython, écrit en C). En réalité, Python
compile d'abord votre code en bytecode (.pyc), puis ce bytecode est exécuté par
la Python Virtual Machine (PVM). Mais cette compilation est transparente pour vous.
2. 🛠️ Installation et configuration ¶
2.1 Installation de Python ¶
Sur Windows ¶
- Rendez‑vous sur python.org/downloads.
- Téléchargez la dernière version stable (3.12 au moment de l'écriture).
- TRÈS IMPORTANT : cochez la case « Add Python to PATH » lors de l'installation.
- Cliquez sur Install Now.
Pour vérifier que tout fonctionne, ouvrez un terminal (cmd ou PowerShell) :
python --version
Vous devriez voir quelque chose comme Python 3.12.1.
Sur macOS ¶
brew install python
Sur Linux (Debian/Ubuntu) ¶
sudo apt update
sudo apt install python3 python3-pip python3-venv
2.2 Choisir un éditeur de code ¶
Plusieurs choix s'offrent à vous :
- VS Code (recommandé pour débuter) : gratuit, léger, extensible.
- PyCharm (Community Edition gratuite) : IDE complet dédié à Python.
- Sublime Text, Atom, Vim, Emacs : pour les puristes.
- Jupyter Notebook : pour la data science.
Pour ce cours, j'utiliserai VS Code avec l'extension officielle Python de Microsoft.
2.3 L'interpréteur interactif (REPL) ¶
Tapez simplement python dans un terminal :
Python 3.12.1 (main, Dec 7 2023, 12:00:00)
Type "help", "copyright", "credits" or "license" for more information.
>>>
Le >>> est l'invite (prompt). Vous pouvez taper du code Python directement :
>>> 2 + 2
4
>>> print("Bonjour")
Bonjour
>>> exit()
Pour quitter : exit() ou Ctrl+Z puis Entrée (Windows), ou Ctrl+D (Linux/Mac).
2.4 Exécuter un script ¶
Créez un fichier hello.py :
print("Hello, World!")
Puis dans un terminal :
python hello.py
3. 📝 Premier programme et syntaxe générale ¶
3.1 Le sacro‑saint « Hello, World! » ¶
print("Hello, World!")
print() est une fonction intégrée (built‑in) qui affiche du texte dans la console.
Les guillemets (" ou ') délimitent une chaîne de caractères.
3.2 Les commentaires ¶
Les commentaires sont ignorés par l'interpréteur. Ils servent à expliquer le code.
# Ceci est un commentaire sur une ligne
"""
Ceci est un commentaire
sur plusieurs lignes
(en réalité, c'est une chaîne non assignée).
"""
x = 10 # Commentaire en fin de ligne
3.3 L'indentation : la signature de Python ¶
En Python, l'indentation n'est pas décorative, elle est syntaxique.
On utilise 4 espaces par niveau (jamais de tabulations mélangées).
if True:
print("Indenté de 4 espaces")
if True:
print("Indenté de 8 espaces")
print("Plus indenté")
Une mauvaise indentation provoque une IndentationError.
3.4 Les instructions multiples ¶
Une instruction par ligne, normalement. On peut en mettre plusieurs avec ; mais c'est
fortement déconseillé :
x = 1; y = 2; z = 3 # À éviter
Pour couper une ligne longue, on utilise le backslash \ ou les parenthèses :
total = 1 + 2 + 3 + \
4 + 5 + 6
total = (1 + 2 + 3 +
4 + 5 + 6)
3.5 Les mots‑clés réservés ¶
Python possède une trentaine de mots‑clés réservés que vous ne pouvez pas utiliser
comme noms de variables :
False None True and as assert async await
break class continue def del elif else except
finally for from global if import in is
lambda nonlocal not or pass raise return try
while with yield
Pour les voir dans votre interpréteur :
import keyword
print(keyword.kwlist)
4. 📦 Variables et types de données ¶
4.1 Qu'est‑ce qu'une variable ? ¶
Une variable est un nom qui pointe vers une valeur stockée en mémoire.
En Python, on n'a pas besoin de déclarer le type : il est déduit automatiquement.
age = 25 # int
prix = 19.99 # float
nom = "Alice" # str
est_majeur = True # bool
4.2 Règles de nommage ¶
- Doit commencer par une lettre ou un underscore
_ - Peut contenir des lettres, chiffres, underscores
- Sensible à la casse :
age≠Age≠AGE - Ne peut pas être un mot‑clé réservé
- Convention : snake_case pour les variables et fonctions
ma_variable = 10 # ✅ Bon
maVariable = 10 # ❌ Style Java, à éviter en Python
2chats = "Tom et Jerry" # ❌ Erreur : commence par un chiffre
_privé = "ok" # ✅ Underscore en début = convention "privé"
4.3 Affectation multiple ¶
a, b, c = 1, 2, 3
x = y = z = 0
a, b = b, a # Échange (swap) de variables, élégant !
4.4 Les types de base ¶
4.4.1 Les entiers (int) ¶
n = 42
grand = 10**100 # Pas de limite, sauf la mémoire
binaire = 0b1010 # = 10
octal = 0o17 # = 15
hexa = 0xFF # = 255
4.4.2 Les flottants (float) ¶
pi = 3.14159
e = 2.718
notation_sci = 1.5e3 # = 1500.0
infini = float('inf')
pas_un_nombre = float('nan')
⚠️ Les flottants sont stockés en binaire IEEE 754 → imprécisions :
>>> 0.1 + 0.2
0.30000000000000004
Pour des calculs précis (finance), utilisez le module decimal.
4.4.3 Les booléens (bool) ¶
vrai = True
faux = False
En interne : True == 1, False == 0.
4.4.4 Les chaînes (str) ¶
prenom = "Alice"
nom = 'Dupont'
phrase = """Une chaîne
sur plusieurs lignes"""
4.4.5 Le type NoneType ¶
None représente l'absence de valeur (équivalent du null d'autres langages).
resultat = None
4.5 Connaître et convertir les types ¶
type(42) # <class 'int'>
type("hello") # <class 'str'>
type(3.14) # <class 'float'>
int("42") # 42
float("3.14") # 3.14
str(42) # "42"
bool(0) # False
bool("a") # True (toute chaîne non vide est True)
list("abc") # ['a', 'b', 'c']
4.6 Saisie utilisateur ¶
nom = input("Quel est ton nom ? ")
print(f"Bonjour, {nom} !")
age = int(input("Quel est ton âge ? ")) # Conversion obligatoire
print(f"Dans 10 ans, tu auras {age + 10} ans.")
input() retourne toujours une chaîne, même si l'utilisateur tape un nombre.
5. ➕ Les opérateurs ¶
5.1 Opérateurs arithmétiques ¶
| Opérateur | Description | Exemple | Résultat |
|---|---|---|---|
+ |
Addition | 5 + 3 |
8 |
- |
Soustraction | 5 - 3 |
2 |
* |
Multiplication | 5 * 3 |
15 |
/ |
Division | 7 / 2 |
3.5 |
// |
Division entière | 7 // 2 |
3 |
% |
Modulo | 7 % 2 |
1 |
** |
Puissance | 2 ** 10 |
1024 |
print(17 / 5) # 3.4
print(17 // 5) # 3 (quotient entier)
print(17 % 5) # 2 (reste)
print(2 ** 8) # 256
5.2 Opérateurs de comparaison ¶
| Opérateur | Signification |
|---|---|
== |
Égal à |
!= |
Différent de |
< |
Strictement inférieur |
> |
Strictement supérieur |
<= |
Inférieur ou égal |
>= |
Supérieur ou égal |
Ils retournent un bool :
print(5 == 5) # True
print(5 != 3) # True
print("a" < "b") # True (ordre lexicographique)
5.3 Opérateurs logiques ¶
True and False # False
True or False # True
not True # False
Python utilise l'évaluation paresseuse (short‑circuit) :
def f():
print("appelé")
return True
True or f() # f() n'est PAS appelée
False and f() # f() n'est PAS appelée
5.4 Opérateurs d'affectation composés ¶
x = 10
x += 5 # x = x + 5 → 15
x -= 3 # x = x - 3 → 12
x *= 2 # x = x * 2 → 24
x /= 4 # x = x / 4 → 6.0
x //= 2 # x = x // 2 → 3.0
x **= 2 # x = x ** 2 → 9.0
x %= 4 # x = x % 4 → 1.0
5.5 Opérateurs d'identité et d'appartenance ¶
# is / is not : compare l'identité (même objet en mémoire)
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True (même contenu)
print(a is b) # False (objets différents)
print(a is c) # True (même objet)
# in / not in : appartenance
print(3 in [1, 2, 3]) # True
print("a" in "chat") # True
print("z" not in "chat") # True
5.6 Priorité des opérateurs ¶
Du plus prioritaire au moins prioritaire (extrait) :
**+x,-x(unaire),~x*,/,//,%+,-- Comparaisons (
<,<=,>,>=,!=,==) notandor
En cas de doute → parenthèses ! Elles rendent le code plus clair.
print(2 + 3 * 4) # 14
print((2 + 3) * 4) # 20
6. 🔤 Les chaînes de caractères en profondeur ¶
6.1 Création ¶
s1 = "double"
s2 = 'simple'
s3 = "L'apostrophe ne pose pas de problème"
s4 = 'Il a dit "bonjour"'
s5 = """Multi‑
ligne"""
s6 = "Ligne 1\nLigne 2" # \n = saut de ligne
6.2 Caractères spéciaux (échappement) ¶
| Séquence | Signification |
|---|---|
\n |
Saut de ligne |
\t |
Tabulation |
\\ |
Backslash |
\" |
Guillemet double |
\' |
Apostrophe |
\u00e9 |
Caractère Unicode (é) |
Pour ignorer les échappements (utile pour les chemins Windows ou les regex) :
chemin = r"C:\Users\Alice\Documents" # raw string
6.3 Concaténation et répétition ¶
salut = "Hello, " + "World!"
ligne = "-" * 30 # "------------------------------"
6.4 Indexation et tranches (slicing) ¶
Une chaîne est une séquence. Chaque caractère a un index, à partir de 0.
s = "Python"
# 0 1 2 3 4 5
# -6-5-4-3-2-1
print(s[0]) # 'P'
print(s[-1]) # 'n'
print(s[1:4]) # 'yth' (de l'index 1 inclus à 4 exclu)
print(s[:3]) # 'Pyt'
print(s[3:]) # 'hon'
print(s[::2]) # 'Pto' (un caractère sur deux)
print(s[::-1]) # 'nohtyP' (chaîne inversée)
⚠️ Les chaînes sont immuables : s[0] = "Q" provoque une erreur.
6.5 Les méthodes de chaînes ¶
s = " Bonjour le Monde "
s.upper() # " BONJOUR LE MONDE "
s.lower() # " bonjour le monde "
s.title() # " Bonjour Le Monde "
s.strip() # "Bonjour le Monde"
s.lstrip() # "Bonjour le Monde "
s.rstrip() # " Bonjour le Monde"
s.replace("Monde", "Python")
s.split() # ['Bonjour', 'le', 'Monde']
s.split("o") # [' B', 'nj', 'ur le M', 'nde ']
"-".join(["a", "b", "c"]) # "a-b-c"
s.startswith(" Bon") # True
s.endswith("de ") # True
s.find("le") # 9 (index, ou -1 si non trouvé)
s.count("o") # 3
s.isdigit() # False
"123".isdigit() # True
"abc".isalpha() # True
"abc123".isalnum() # True
len(s) # 20
6.6 Le formatage de chaînes ¶
6.6.1 f‑strings (recommandé, Python 3.6+) ¶
nom = "Alice"
age = 30
print(f"Je m'appelle {nom} et j'ai {age} ans.")
print(f"L'an prochain, j'aurai {age + 1} ans.")
print(f"{3.14159:.2f}") # 3.14
print(f"{1000000:,}") # 1,000,000
print(f"{42:>10}") # alignement à droite sur 10 caractères
print(f"{42:<10}|") # alignement à gauche
print(f"{42:^10}") # centré
print(f"{42:08d}") # 00000042
6.6.2 La méthode .format() ¶
"Je m'appelle {} et j'ai {} ans.".format(nom, age)
"{0} {1} {0}".format("ha", "hi") # "ha hi ha"
"{nom} a {age} ans".format(nom="Bob", age=20)
6.6.3 L'ancien style % (à éviter dans le code moderne) ¶
"%s a %d ans" % (nom, age)
7. 🔀 Les structures conditionnelles ¶
7.1 if / elif / else ¶
age = 18
if age < 13:
print("Enfant")
elif age < 18:
print("Adolescent")
elif age < 65:
print("Adulte")
else:
print("Senior")
7.2 Conditions composées ¶
note = 14
present = True
if note >= 10 and present:
print("Validé")
if note < 5 or not present:
print("Échec")
7.3 Valeurs truthy et falsy ¶
En Python, beaucoup de valeurs sont considérées comme fausses dans un contexte
booléen :
FalseNone0,0.0,0j""(chaîne vide)[],(),{},set()(collections vides)
Tout le reste est truthy.
if []:
print("Liste non vide") # Ne s'affiche pas
else:
print("Liste vide") # ✅
7.4 L'opérateur ternaire ¶
age = 20
statut = "majeur" if age >= 18 else "mineur"
7.5 Le match (Python 3.10+) ¶
Équivalent du switch d'autres langages, en plus puissant :
def décrire(jour):
match jour:
case "lundi" | "mardi" | "mercredi" | "jeudi" | "vendredi":
return "Semaine"
case "samedi" | "dimanche":
return "Week‑end"
case _:
return "Inconnu"
8. 🔁 Les boucles ¶
8.1 La boucle while ¶
i = 0
while i < 5:
print(i)
i += 1
⚠️ Attention aux boucles infinies ! Toujours s'assurer que la condition deviendra fausse.
8.2 La boucle for ¶
En Python, for itère sur les éléments d'une séquence ou d'un itérable.
for lettre in "Python":
print(lettre)
for nombre in [1, 2, 3, 4, 5]:
print(nombre)
8.3 La fonction range() ¶
range(5) # 0, 1, 2, 3, 4
range(2, 8) # 2, 3, 4, 5, 6, 7
range(0, 10, 2) # 0, 2, 4, 6, 8
range(10, 0, -1) # 10, 9, ..., 1
for i in range(5):
print(i)
8.4 break et continue ¶
# break : sortir de la boucle
for i in range(10):
if i == 5:
break
print(i) # 0, 1, 2, 3, 4
# continue : passer à l'itération suivante
for i in range(10):
if i % 2 == 0:
continue
print(i) # 1, 3, 5, 7, 9
8.5 La clause else des boucles ¶
Le else s'exécute si la boucle se termine sans break :
for n in [2, 3, 5, 7]:
if n % 2 == 0:
print("Pair trouvé")
break
else:
print("Tous impairs")
8.6 Boucles imbriquées ¶
for i in range(1, 4):
for j in range(1, 4):
print(f"{i} x {j} = {i*j}")
8.7 enumerate(), zip(), reversed() ¶
fruits = ["pomme", "banane", "kiwi"]
for i, fruit in enumerate(fruits):
print(i, fruit)
prix = [1.0, 0.5, 2.0]
for fruit, p in zip(fruits, prix):
print(f"{fruit} : {p} €")
for fruit in reversed(fruits):
print(fruit)
9. 🧩 Les fonctions ¶
9.1 Définir une fonction ¶
def saluer(nom):
"""Affiche un message de bienvenue."""
print(f"Bonjour, {nom} !")
saluer("Alice")
La chaîne entre triples guillemets est appelée docstring : elle documente la fonction.
9.2 Retourner une valeur ¶
def carre(x):
return x * x
resultat = carre(5) # 25
Une fonction sans return retourne implicitement None.
9.3 Plusieurs valeurs de retour ¶
def min_max(liste):
return min(liste), max(liste)
mini, maxi = min_max([3, 1, 4, 1, 5, 9, 2, 6])
En réalité, on retourne un tuple.
9.4 Arguments par défaut ¶
def saluer(nom, salutation="Bonjour"):
print(f"{salutation}, {nom} !")
saluer("Alice") # Bonjour, Alice !
saluer("Bob", "Salut") # Salut, Bob !
saluer(nom="Carol") # Bonjour, Carol !
⚠️ Piège : ne jamais utiliser de valeur mutable comme défaut !
def ajouter(item, liste=[]): # ❌ DANGER
liste.append(item)
return liste
print(ajouter(1)) # [1]
print(ajouter(2)) # [1, 2] ← La liste est partagée !
def ajouter(item, liste=None): # ✅ Bonne pratique
if liste is None:
liste = []
liste.append(item)
return liste
9.5 Arguments positionnels et nommés ¶
def présenter(prenom, nom, age):
print(f"{prenom} {nom}, {age} ans")
présenter("Alice", "Dupont", 30) # positionnel
présenter(age=30, prenom="Alice", nom="Dupont") # nommé
9.6 *args et **kwargs ¶
def somme(*nombres):
"""Accepte un nombre variable d'arguments positionnels."""
return sum(nombres)
print(somme(1, 2, 3, 4, 5)) # 15
def afficher_infos(**infos):
"""Accepte un nombre variable d'arguments nommés."""
for cle, valeur in infos.items():
print(f"{cle} : {valeur}")
afficher_infos(nom="Alice", age=30, ville="Paris")
On peut combiner les quatre types d'arguments :
def fonction(a, b, *args, option=True, **kwargs):
...
9.7 Portée des variables (scope) ¶
Python suit la règle LEGB : Local → Enclosing → Global → Built‑in.
x = "global"
def externe():
x = "enclosing"
def interne():
x = "local"
print(x) # local
interne()
print(x) # enclosing
externe()
print(x) # global
Les mots‑clés global et nonlocal permettent de modifier des variables externes :
compteur = 0
def incrementer():
global compteur
compteur += 1
incrementer()
incrementer()
print(compteur) # 2
9.8 Les fonctions lambda ¶
Fonctions anonymes, sur une ligne :
carre = lambda x: x ** 2
print(carre(4)) # 16
# Très utile avec sorted, map, filter
points = [(1, 3), (5, 1), (2, 7)]
points.sort(key=lambda p: p[1])
9.9 Fonctions comme objets ¶
En Python, les fonctions sont des objets de première classe : on peut les passer
en argument, les retourner, les stocker dans des variables.
def double(x): return x * 2
def triple(x): return x * 3
operations = [double, triple]
for op in operations:
print(op(5)) # 10, puis 15
9.10 map, filter, reduce ¶
nombres = [1, 2, 3, 4, 5]
doubles = list(map(lambda x: x * 2, nombres))
pairs = list(filter(lambda x: x % 2 == 0, nombres))
from functools import reduce
total = reduce(lambda a, b: a + b, nombres) # 15
10. 📚 Les collections ¶
10.1 Les listes ¶
Les listes sont des séquences ordonnées et mutables.
10.1.1 Création ¶
vide = []
nombres = [1, 2, 3, 4, 5]
mixte = [1, "deux", 3.0, True, None]
nestée = [[1, 2], [3, 4], [5, 6]]
liste = list(range(10))
10.1.2 Accès et modification ¶
fruits = ["pomme", "banane", "kiwi"]
print(fruits[0]) # pomme
print(fruits[-1]) # kiwi
fruits[1] = "fraise"
print(fruits) # ['pomme', 'fraise', 'kiwi']
# Slicing comme pour les chaînes
print(fruits[0:2]) # ['pomme', 'fraise']
print(fruits[::-1]) # liste inversée
10.1.3 Méthodes principales ¶
liste = [3, 1, 4, 1, 5]
liste.append(9) # [3, 1, 4, 1, 5, 9]
liste.insert(0, 99) # [99, 3, 1, 4, 1, 5, 9]
liste.extend([2, 6]) # [99, 3, 1, 4, 1, 5, 9, 2, 6]
liste.remove(1) # supprime le PREMIER 1
liste.pop() # supprime et retourne le dernier
liste.pop(0) # supprime et retourne celui d'index 0
liste.index(4) # 1 (position de la première occurrence)
liste.count(1) # 1
liste.sort() # trie sur place (croissant)
liste.sort(reverse=True)
liste.reverse() # inverse sur place
liste.clear() # vide la liste
copie = liste.copy() # copie superficielle
10.1.4 Tri non destructif : sorted() ¶
liste = [3, 1, 4, 1, 5]
nouvelle = sorted(liste) # liste inchangée
décroissant = sorted(liste, reverse=True)
mots = sorted(["banane", "abricot"], key=len)
10.1.5 Concaténation et répétition ¶
[1, 2] + [3, 4] # [1, 2, 3, 4]
[0] * 5 # [0, 0, 0, 0, 0]
10.1.6 ⚠️ Copie vs référence ¶
a = [1, 2, 3]
b = a # b pointe vers la MÊME liste
b.append(4)
print(a) # [1, 2, 3, 4] !
c = a.copy() # ou list(a), ou a[:]
c.append(5)
print(a) # [1, 2, 3, 4] (inchangé)
Pour copier en profondeur (listes imbriquées) :
import copy
deep = copy.deepcopy(a)
10.2 Les tuples ¶
Les tuples sont comme les listes, mais immuables.
point = (3, 4)
solo = (5,) # ⚠️ la virgule est obligatoire pour un singleton
sans_paren = 1, 2, 3 # tuple aussi !
x, y = point # déballage (unpacking)
print(point[0]) # 3
# point[0] = 10 # ❌ TypeError
Avantages des tuples :
- Plus rapides que les listes
- Utilisables comme clés de dictionnaires
- Communiquent l'intention « ces données ne changeront pas »
10.3 Les dictionnaires ¶
Structure clé/valeur (équivalent des « hash maps »).
10.3.1 Création et accès ¶
personne = {
"nom": "Dupont",
"prenom": "Alice",
"age": 30
}
print(personne["nom"]) # Dupont
print(personne.get("email")) # None (pas d'erreur)
print(personne.get("email", "N/A")) # "N/A"
personne["email"] = "alice@ex.fr" # ajout / modification
del personne["age"] # suppression
10.3.2 Itération ¶
for cle in personne:
print(cle)
for cle, valeur in personne.items():
print(f"{cle} = {valeur}")
for valeur in personne.values():
print(valeur)
10.3.3 Méthodes utiles ¶
personne.keys()
personne.values()
personne.items()
personne.update({"ville": "Paris", "age": 31})
personne.pop("ville")
personne.setdefault("pays", "France")
"nom" in personne # True
len(personne)
personne.clear()
10.3.4 Dictionnaires imbriqués ¶
contacts = {
"alice": {"tel": "0102", "email": "a@x.fr"},
"bob": {"tel": "0304", "email": "b@x.fr"},
}
print(contacts["alice"]["email"])
10.4 Les ensembles (set) ¶
Collections non ordonnées d'éléments uniques.
fruits = {"pomme", "banane", "kiwi"}
fruits.add("fraise")
fruits.discard("banane") # pas d'erreur si absent
fruits.remove("kiwi") # KeyError si absent
# Élimination des doublons
nombres = [1, 2, 2, 3, 3, 3, 4]
uniques = list(set(nombres)) # [1, 2, 3, 4]
# Opérations ensemblistes
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # union {1, 2, 3, 4, 5, 6}
print(a & b) # intersection {3, 4}
print(a - b) # différence {1, 2}
print(a ^ b) # diff. symétrique {1, 2, 5, 6}
⚠️ Le set vide se crée avec set(), pas {} (qui est un dict vide).
10.5 Récapitulatif ¶
| Type | Ordonné | Mutable | Doublons | Indexable |
|---|---|---|---|---|
list |
✅ | ✅ | ✅ | ✅ |
tuple |
✅ | ❌ | ✅ | ✅ |
dict |
✅* | ✅ | clés non | par clé |
set |
❌ | ✅ | ❌ | ❌ |
* Depuis Python 3.7, les dicts conservent l'ordre d'insertion.
11. 🚀 Compréhensions et générateurs ¶
11.1 Compréhensions de listes ¶
Syntaxe concise pour créer des listes :
# Approche classique
carres = []
for x in range(10):
carres.append(x ** 2)
# Compréhension équivalente
carres = [x ** 2 for x in range(10)]
Avec condition :
pairs = [x for x in range(20) if x % 2 == 0]
Avec if/else :
parite = ["pair" if x % 2 == 0 else "impair" for x in range(5)]
Imbriquée :
matrice = [[i*j for j in range(3)] for i in range(3)]
# [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
11.2 Compréhensions de dictionnaires ¶
carres = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
inverser = {v: k for k, v in personne.items()}
11.3 Compréhensions d'ensembles ¶
voyelles = {c for c in "Hello, World!" if c.lower() in "aeiou"}
11.4 Expressions génératrices ¶
Comme les compréhensions, mais avec des () : elles produisent les valeurs à la demande
(lazy), donc plus économes en mémoire.
gen = (x ** 2 for x in range(1_000_000))
print(sum(gen)) # Calcule sans stocker un million de carrés en mémoire
12. 📦 Modules et packages ¶
12.1 Importer un module ¶
import math
print(math.pi)
print(math.sqrt(16))
import math as m # alias
from math import pi, sqrt
from math import * # ⚠️ déconseillé (pollue le namespace)
12.2 Créer son propre module ¶
Fichier mes_outils.py :
def saluer(nom):
return f"Bonjour, {nom} !"
PI = 3.14159
Fichier main.py (dans le même dossier) :
import mes_outils
print(mes_outils.saluer("Alice"))
print(mes_outils.PI)
12.3 Le bloc if __name__ == "__main__" ¶
def main():
print("Programme principal")
if __name__ == "__main__":
main()
Ce bloc ne s'exécute que si le fichier est lancé directement (pas s'il est importé).
12.4 Les packages ¶
Un package = un dossier contenant un fichier __init__.py (qui peut être vide).
mon_package/
__init__.py
module1.py
module2.py
from mon_package import module1
from mon_package.module2 import ma_fonction
12.5 La bibliothèque standard (sélection) ¶
| Module | Utilité |
|---|---|
os |
Système d'exploitation, fichiers |
sys |
Interpréteur, arguments |
pathlib |
Manipulation moderne de chemins |
datetime |
Dates et heures |
time |
Pauses, mesures de temps |
math |
Fonctions mathématiques |
random |
Aléatoire |
json |
Parser et écrire du JSON |
csv |
Lire/écrire des CSV |
re |
Expressions régulières |
collections |
Collections avancées (Counter, deque, …) |
itertools |
Outils pour itérateurs |
functools |
Outils pour fonctions |
subprocess |
Lancer des commandes système |
argparse |
Parser des arguments en ligne de commande |
logging |
Journalisation |
urllib |
Téléchargement HTTP basique |
sqlite3 |
Base de données SQLite |
Exemples :
import os
print(os.getcwd()) # dossier courant
print(os.listdir(".")) # contenu du dossier
import random
print(random.randint(1, 10))
print(random.choice(["a", "b", "c"]))
random.shuffle([1, 2, 3, 4])
import datetime
maintenant = datetime.datetime.now()
print(maintenant.strftime("%d/%m/%Y %H:%M"))
import time
debut = time.time()
time.sleep(1)
print(f"Écoulé : {time.time() - debut:.3f} s")
12.6 Installer des paquets externes avec pip ¶
pip install requests
pip install --upgrade pandas
pip uninstall numpy
pip list
pip freeze > requirements.txt
pip install -r requirements.txt
13. 📁 Gestion des fichiers ¶
13.1 Ouvrir et lire un fichier ¶
fichier = open("texte.txt", "r", encoding="utf-8")
contenu = fichier.read()
fichier.close()
⚠️ Toujours fermer un fichier. La meilleure pratique est d'utiliser with :
with open("texte.txt", "r", encoding="utf-8") as f:
contenu = f.read()
# Le fichier est fermé automatiquement à la sortie du bloc
13.2 Modes d'ouverture ¶
| Mode | Description |
|---|---|
"r" |
Lecture (par défaut). Erreur si le fichier n'existe pas |
"w" |
Écriture. Écrase le fichier existant |
"a" |
Ajout (append) à la fin |
"x" |
Création exclusive (erreur si existe) |
"b" |
Binaire (à combiner : "rb", "wb") |
"t" |
Texte (par défaut) |
"+" |
Lecture et écriture ("r+", "w+") |
13.3 Lire ligne par ligne ¶
with open("texte.txt", encoding="utf-8") as f:
for ligne in f:
print(ligne.rstrip()) # rstrip pour retirer le \n
# Ou bien
with open("texte.txt", encoding="utf-8") as f:
lignes = f.readlines() # liste de lignes
13.4 Écrire dans un fichier ¶
with open("sortie.txt", "w", encoding="utf-8") as f:
f.write("Première ligne\n")
f.write("Deuxième ligne\n")
f.writelines(["Trois\n", "Quatre\n"])
13.5 Le module pathlib (moderne) ¶
from pathlib import Path
p = Path("dossier/fichier.txt")
print(p.exists())
print(p.is_file())
print(p.parent) # dossier
print(p.name) # fichier.txt
print(p.stem) # fichier
print(p.suffix) # .txt
print(p.absolute())
# Lire / écrire en une ligne
texte = p.read_text(encoding="utf-8")
p.write_text("nouveau contenu", encoding="utf-8")
# Parcourir un dossier
for fichier in Path(".").glob("*.py"):
print(fichier)
# Récursivement
for fichier in Path(".").rglob("*.txt"):
print(fichier)
13.6 JSON ¶
import json
data = {"nom": "Alice", "âge": 30, "loisirs": ["lecture", "vélo"]}
# Écrire
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# Lire
with open("data.json", encoding="utf-8") as f:
chargé = json.load(f)
# Conversions chaîne ↔ dict
texte = json.dumps(data)
parsed = json.loads(texte)
13.7 CSV ¶
import csv
# Écrire
with open("personnes.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["nom", "âge"])
writer.writerow(["Alice", 30])
writer.writerow(["Bob", 25])
# Lire
with open("personnes.csv", encoding="utf-8") as f:
reader = csv.reader(f)
for ligne in reader:
print(ligne)
# Avec dictionnaires
with open("personnes.csv", encoding="utf-8") as f:
reader = csv.DictReader(f)
for ligne in reader:
print(ligne["nom"], ligne["âge"])
14. ⚠️ La gestion des exceptions ¶
14.1 Pourquoi gérer les exceptions ? ¶
Une exception non gérée fait planter le programme. Les exceptions permettent de
réagir aux erreurs au lieu de subir.
14.2 try / except ¶
try:
x = int(input("Un nombre : "))
print(10 / x)
except ValueError:
print("Ce n'est pas un nombre valide.")
except ZeroDivisionError:
print("On ne divise pas par zéro.")
except Exception as e:
print(f"Erreur inattendue : {e}")
14.3 else et finally ¶
try:
f = open("data.txt")
except FileNotFoundError:
print("Fichier introuvable")
else:
# exécuté seulement si AUCUNE exception n'a eu lieu
print(f.read())
f.close()
finally:
# exécuté DANS TOUS LES CAS
print("Nettoyage terminé")
14.4 Hiérarchie des exceptions courantes ¶
BaseException
└── Exception
├── ArithmeticError
│ └── ZeroDivisionError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── ValueError
├── TypeError
├── FileNotFoundError
├── OSError
└── ...
Cibler une exception précise est toujours préférable.
14.5 Lever une exception ¶
def racine_carree(x):
if x < 0:
raise ValueError("x doit être positif ou nul")
return x ** 0.5
14.6 Créer ses propres exceptions ¶
class SoldeInsuffisantError(Exception):
"""Levée quand un compte n'a pas assez de fonds."""
def retirer(compte, montant):
if montant > compte["solde"]:
raise SoldeInsuffisantError("Manque de fonds")
compte["solde"] -= montant
15. 🏛️ La programmation orientée objet ¶
15.1 Concepts ¶
- Classe : modèle / patron.
- Objet (instance) : une réalisation concrète d'une classe.
- Attribut : variable rattachée à un objet.
- Méthode : fonction rattachée à un objet.
15.2 Définir une classe ¶
class Personne:
"""Représente une personne."""
# Attribut de classe (partagé)
espece = "Homo sapiens"
def __init__(self, nom, age):
# Attributs d'instance
self.nom = nom
self.age = age
def se_presenter(self):
print(f"Je m'appelle {self.nom} et j'ai {self.age} ans.")
alice = Personne("Alice", 30)
alice.se_presenter()
print(alice.nom)
print(Personne.espece)
self représente l'instance en cours. Toujours en premier paramètre des méthodes.
15.3 Méthode __init__ (constructeur) ¶
Appelée automatiquement à la création de l'objet.
15.4 Méthodes spéciales (dunder methods) ¶
class Vecteur:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Vecteur({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
def __add__(self, autre):
return Vecteur(self.x + autre.x, self.y + autre.y)
def __eq__(self, autre):
return self.x == autre.x and self.y == autre.y
def __len__(self):
return int((self.x ** 2 + self.y ** 2) ** 0.5)
v1 = Vecteur(1, 2)
v2 = Vecteur(3, 4)
print(v1 + v2) # (4, 6)
print(v1 == Vecteur(1, 2)) # True
Quelques méthodes spéciales courantes :
| Méthode | Rôle |
|---|---|
__init__ |
constructeur |
__repr__ |
représentation officielle (debug) |
__str__ |
conversion en chaîne (str()) |
__len__ |
len(obj) |
__getitem__ |
obj[key] |
__setitem__ |
obj[key] = ... |
__iter__ |
itérable |
__call__ |
rendre l'objet appelable |
__eq__, __lt__, … |
comparaisons |
__add__, __mul__, … |
opérateurs arithmétiques |
15.5 Encapsulation et conventions ¶
Python n'a pas de vrai private, mais des conventions :
attribut: public._attribut: usage interne (convention « ne pas toucher »).__attribut: name mangling (renommé en_Classe__attribut).
class CompteBancaire:
def __init__(self, solde=0):
self._solde = solde
def deposer(self, montant):
if montant <= 0:
raise ValueError("Montant invalide")
self._solde += montant
@property
def solde(self):
return self._solde
Le décorateur @property permet d'accéder à une méthode comme à un attribut :
compte.solde au lieu de compte.solde().
15.6 Héritage ¶
class Animal:
def __init__(self, nom):
self.nom = nom
def crier(self):
print("Bruit générique")
class Chien(Animal):
def crier(self):
print(f"{self.nom} fait Wouf !")
class Chat(Animal):
def __init__(self, nom, couleur):
super().__init__(nom) # appelle le constructeur parent
self.couleur = couleur
def crier(self):
print(f"{self.nom} fait Miaou !")
rex = Chien("Rex")
rex.crier() # Rex fait Wouf !
15.7 Polymorphisme ¶
animaux = [Chien("Rex"), Chat("Mimi", "noir")]
for a in animaux:
a.crier() # Chacun crie selon sa classe
15.8 Classes abstraites ¶
from abc import ABC, abstractmethod
class Forme(ABC):
@abstractmethod
def aire(self):
...
class Carre(Forme):
def __init__(self, cote):
self.cote = cote
def aire(self):
return self.cote ** 2
# f = Forme() # ❌ TypeError
c = Carre(5)
print(c.aire()) # 25
15.9 Méthodes de classe et statiques ¶
class Math:
PI = 3.14159
@classmethod
def aire_disque(cls, r):
return cls.PI * r ** 2
@staticmethod
def carre(x):
return x * x
print(Math.aire_disque(2))
print(Math.carre(5))
15.10 Dataclasses (Python 3.7+) ¶
Pour créer rapidement des classes « porteuses de données » :
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
p = Point(1.0, 2.0)
print(p) # Point(x=1.0, y=2.0)
print(p == Point(1.0, 2.0)) # True
16. 🔄 Itérateurs et générateurs ¶
16.1 Le protocole d'itération ¶
Un objet est itérable s'il possède une méthode __iter__() qui retourne un
itérateur (objet ayant __next__()).
liste = [1, 2, 3]
it = iter(liste)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# next(it) # StopIteration
16.2 Créer un itérateur ¶
class Compteur:
def __init__(self, max):
self.max = max
self.n = 0
def __iter__(self):
return self
def __next__(self):
if self.n >= self.max:
raise StopIteration
self.n += 1
return self.n
for n in Compteur(3):
print(n) # 1, 2, 3
16.3 Les générateurs ¶
Bien plus simples ! Une fonction qui contient yield est un générateur :
def compteur(max):
n = 0
while n < max:
n += 1
yield n
for x in compteur(5):
print(x)
Avantage : la valeur est produite à la demande, pas stockée en mémoire.
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
import itertools
for n in itertools.islice(fibonacci(), 10):
print(n) # 10 premiers nombres de Fibonacci
17. 🎀 Les décorateurs ¶
Un décorateur est une fonction qui modifie une autre fonction.
17.1 Premier décorateur ¶
def majuscule(fonction):
def wrapper(*args, **kwargs):
resultat = fonction(*args, **kwargs)
return resultat.upper()
return wrapper
@majuscule
def saluer(nom):
return f"bonjour {nom}"
print(saluer("alice")) # BONJOUR ALICE
@majuscule est équivalent à saluer = majuscule(saluer).
17.2 Décorateur de chronométrage ¶
import time
from functools import wraps
def chrono(fonction):
@wraps(fonction)
def wrapper(*args, **kwargs):
debut = time.perf_counter()
resultat = fonction(*args, **kwargs)
duree = time.perf_counter() - debut
print(f"{fonction.__name__} a pris {duree:.4f} s")
return resultat
return wrapper
@chrono
def calcul_lent():
time.sleep(1)
return 42
calcul_lent()
@wraps préserve le nom et la docstring de la fonction originale.
17.3 Décorateurs avec paramètres ¶
def repeter(n):
def decorateur(fonction):
def wrapper(*args, **kwargs):
for _ in range(n):
fonction(*args, **kwargs)
return wrapper
return decorateur
@repeter(3)
def coucou():
print("coucou")
coucou() # affiche 3 fois
18. 💻 Le scripting en pratique ¶
18.1 Le shebang (Linux/Mac) ¶
En tête de fichier :
#!/usr/bin/env python3
Puis chmod +x mon_script.py et on peut lancer ./mon_script.py.
18.2 Arguments en ligne de commande : sys.argv ¶
import sys
print("Nom du script :", sys.argv[0])
print("Arguments :", sys.argv[1:])
python script.py foo bar 42
# Arguments : ['foo', 'bar', '42']
18.3 argparse : la solution professionnelle ¶
import argparse
parser = argparse.ArgumentParser(description="Calcule la somme de deux nombres.")
parser.add_argument("a", type=int, help="premier nombre")
parser.add_argument("b", type=int, help="second nombre")
parser.add_argument("--produit", action="store_true",
help="calcule aussi le produit")
args = parser.parse_args()
print(f"Somme : {args.a + args.b}")
if args.produit:
print(f"Produit : {args.a * args.b}")
python script.py 3 5 --produit
18.4 Variables d'environnement ¶
import os
print(os.environ.get("PATH"))
print(os.environ.get("MA_VAR", "valeur par défaut"))
os.environ["MA_VAR"] = "hello"
18.5 Lancer des commandes système ¶
import subprocess
# Méthode moderne (Python 3.5+)
resultat = subprocess.run(["ls", "-la"], capture_output=True, text=True)
print(resultat.stdout)
print("Code retour :", resultat.returncode)
18.6 Codes de retour ¶
import sys
if erreur_critique:
sys.exit(1) # code != 0 → échec
sys.exit(0) # succès
19. 🔍 Les expressions régulières ¶
Module re, indispensable pour les manipulations de texte avancées.
import re
texte = "Mon numéro est 06-12-34-56-78 et l'autre 0712345678."
# Recherche
match = re.search(r"\d{2}-\d{2}-\d{2}-\d{2}-\d{2}", texte)
if match:
print(match.group()) # 06-12-34-56-78
# Trouver toutes les occurrences
nombres = re.findall(r"\d+", texte)
print(nombres) # ['06', '12', '34', '56', '78', '0712345678']
# Remplacement
masqué = re.sub(r"\d", "*", texte)
# Découpage
parties = re.split(r"\s+", " hello world python ")
Quelques motifs essentiels :
| Motif | Signification |
|---|---|
. |
Tout caractère sauf saut de ligne |
\d |
Chiffre [0-9] |
\D |
Non‑chiffre |
\w |
Caractère « mot » (lettre, chiffre, _) |
\s |
Espace blanc |
^ / $ |
Début / fin de chaîne |
* |
0 ou plus |
+ |
1 ou plus |
? |
0 ou 1 |
{n} |
exactement n fois |
{n,m} |
de n à m fois |
[abc] |
a, b ou c |
[^abc] |
tout sauf a, b, c |
(...) |
groupe de capture |
| |
OU logique |
20. 🌟 Bonnes pratiques ¶
20.1 PEP 8 : le style officiel ¶
- 4 espaces par indentation (jamais de tab).
- Lignes de 79 caractères maximum (ou 99 selon les conventions modernes).
- 2 lignes vides entre fonctions/classes au niveau top, 1 ligne dans une classe.
- snake_case pour fonctions et variables.
- PascalCase pour les classes.
- UPPER_CASE pour les constantes.
- Espaces autour des opérateurs :
x = 1, pasx=1. - Pas d'espace avant
(,[,:.
Outils :
pip install black flake8 ruff
black mon_fichier.py
flake8 mon_fichier.py
ruff check .
20.2 Environnements virtuels ¶
Isolent les dépendances par projet.
# Création
python -m venv venv
# Activation
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
# Désactivation
deactivate
Une fois activé, pip install ... n'installe que dans cet environnement.
20.3 Le typage statique (annotations) ¶
Optionnel mais très utile :
def addition(a: int, b: int) -> int:
return a + b
nom: str = "Alice"
notes: list[float] = [12.5, 14.0, 16.5]
from typing import Optional, Union
def trouver(nom: str) -> Optional[dict]:
...
Vérification statique avec mypy :
pip install mypy
mypy mon_fichier.py
20.4 Le module logging plutôt que print ¶
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
logging.debug("détail technique")
logging.info("information")
logging.warning("attention")
logging.error("erreur")
logging.critical("critique")
20.5 Tests unitaires avec unittest ou pytest ¶
# test_calc.py
def addition(a, b):
return a + b
def test_addition():
assert addition(2, 3) == 5
assert addition(-1, 1) == 0
pip install pytest
pytest
20.6 Le Zen de Python ¶
import this
Quelques principes :
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Readability counts.
- Errors should never pass silently.
- There should be one—and preferably only one—obvious way to do it.
21. 🎓 Mini‑projets de fin de cours ¶
21.1 Projet 1 — Jeu du « plus ou moins » ¶
import random
def jeu():
secret = random.randint(1, 100)
essais = 0
print("J'ai choisi un nombre entre 1 et 100. À toi !")
while True:
try:
proposition = int(input("> "))
except ValueError:
print("Entre un entier valide.")
continue
essais += 1
if proposition < secret:
print("Plus grand !")
elif proposition > secret:
print("Plus petit !")
else:
print(f"Bravo ! Trouvé en {essais} essais.")
break
if __name__ == "__main__":
jeu()
21.2 Projet 2 — Gestionnaire de tâches en JSON ¶
import json
from pathlib import Path
FICHIER = Path("taches.json")
def charger():
if not FICHIER.exists():
return []
return json.loads(FICHIER.read_text(encoding="utf-8"))
def sauver(taches):
FICHIER.write_text(
json.dumps(taches, ensure_ascii=False, indent=2),
encoding="utf-8"
)
def ajouter(titre):
taches = charger()
taches.append({"titre": titre, "fait": False})
sauver(taches)
def lister():
for i, t in enumerate(charger(), start=1):
statut = "✓" if t["fait"] else " "
print(f"{i}. [{statut}] {t['titre']}")
def cocher(num):
taches = charger()
taches[num - 1]["fait"] = True
sauver(taches)
def menu():
while True:
print("\n1) Ajouter 2) Lister 3) Cocher 4) Quitter")
choix = input("> ").strip()
if choix == "1":
ajouter(input("Titre : "))
elif choix == "2":
lister()
elif choix == "3":
cocher(int(input("Numéro : ")))
elif choix == "4":
break
if __name__ == "__main__":
menu()
21.3 Projet 3 — Compteur de mots dans un fichier ¶
import sys
import re
from collections import Counter
def compter(chemin, top=10):
with open(chemin, encoding="utf-8") as f:
texte = f.read().lower()
mots = re.findall(r"[a-zàâäéèêëïîôöùûüç]+", texte)
compteur = Counter(mots)
for mot, n in compteur.most_common(top):
print(f"{mot:20} {n}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python compter.py <fichier>")
sys.exit(1)
compter(sys.argv[1])
21.4 Projet 4 — Renommer en masse des fichiers ¶
from pathlib import Path
import argparse
def renommer(dossier, prefixe):
p = Path(dossier)
for i, fichier in enumerate(sorted(p.iterdir()), start=1):
if fichier.is_file():
nouveau = p / f"{prefixe}_{i:03d}{fichier.suffix}"
print(f"{fichier.name} → {nouveau.name}")
fichier.rename(nouveau)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("dossier")
parser.add_argument("prefixe")
args = parser.parse_args()
renommer(args.dossier, args.prefixe)
21.5 Projet 5 — Mini gestionnaire de contacts (POO) ¶
from dataclasses import dataclass, asdict
import json
from pathlib import Path
@dataclass
class Contact:
nom: str
tel: str
email: str = ""
class Carnet:
def __init__(self, fichier="carnet.json"):
self.fichier = Path(fichier)
self.contacts: list[Contact] = []
self.charger()
def charger(self):
if self.fichier.exists():
data = json.loads(self.fichier.read_text(encoding="utf-8"))
self.contacts = [Contact(**c) for c in data]
def sauver(self):
data = [asdict(c) for c in self.contacts]
self.fichier.write_text(
json.dumps(data, ensure_ascii=False, indent=2),
encoding="utf-8"
)
def ajouter(self, contact: Contact):
self.contacts.append(contact)
self.sauver()
def chercher(self, motif: str) -> list[Contact]:
motif = motif.lower()
return [c for c in self.contacts if motif in c.nom.lower()]
def __repr__(self):
return "\n".join(f"- {c.nom} : {c.tel}" for c in self.contacts)
if __name__ == "__main__":
carnet = Carnet()
carnet.ajouter(Contact("Alice", "0102030405", "alice@ex.fr"))
carnet.ajouter(Contact("Bob", "0607080910"))
print(carnet)
print("---")
print(carnet.chercher("ali"))
🏁 Conclusion ¶
Tu disposes maintenant de toutes les bases pour scripter en Python :
✅ Syntaxe et types de base
✅ Structures de contrôle, fonctions
✅ Collections (list, tuple, dict, set)
✅ Modules, fichiers, exceptions
✅ POO, itérateurs, générateurs, décorateurs
✅ Scripting (argparse, sys, subprocess)
✅ Bonnes pratiques (PEP 8, venv, typage)
Prochaines étapes recommandées ¶
- Pratique, pratique, pratique. Refais chaque exemple sans regarder.
- Choisis un projet personnel (scraper un site, automatiser une tâche
répétitive, créer un bot Discord, etc.). - Explore une bibliothèque selon tes intérêts :
- Web :
requests,Flask,FastAPI - Data :
pandas,numpy,matplotlib - Automation :
selenium,pyautogui,schedule - GUI :
tkinter,PyQt,customtkinter
- Web :
- Lis du code existant sur GitHub : c'est le meilleur moyen de progresser.
- Apprends Git pour versionner tes scripts.
Bonne route avec Python ! 🐍✨
Comments
Please login to leave a comment.
No comments yet. Be the first to comment!