🐍 Python – Le Guide Ultime
Deep Dive (Détaillé) : Syntaxe, POO (Class), Pythonic (Comprehensions), Venv & Écosystème (Web, Data, AI).
1. Philosophie & Syntaxe
"Zen of Python". Typage dynamique fort. L'Indentation (pas de {...}).
2. Types de Base & Slicing
str (.split, .join, f-string), int, bool, None. Slicing ([1:5:2]).
3. Structures (List, Dict, Set)
list (mutable), tuple (immutable), dict (clé/valeur), set (uniques). defaultdict.
4. Fonctions & Contrôle
def, if/elif/else, lambda, *args, **kwargs, try/except. Type Hinting.
5. 🚀 Le Style "Pythonic"
Comprehensions, Generators (yield), Context Managers (with open).
6. POO (Classes & Héritage)
class, self, __init__. Héritage (super()). Méthodes Magiques (__str__).
7. POO Avancé (Addons)
Décorateurs (@decorator), Properties (@property), Dataclasses (@dataclass).
8. Historique des Versions
Évolution sur 10 ans. 3.7 (data classes), 3.8 (walrus), 3.10 (match/case).
9. Modules, Pip & Venv
import, pip, requirements.txt, __init__.py, venv (isolation).
10. Frameworks Web
Django (MVT), Flask (Micro), FastAPI (Moderne/Async). Celery (Tâches).
Django FastAPI Celery11. Frameworks Data & AI
Pandas (DataFrame), NumPy (Arrays), PyTorch/TensorFlow (AI).
Pandas NumPy PyTorch12. Outils, Plugins & Liens
Ruff, Black (Formatters), Pytest (Tests), Poetry. Plugins (Requests, Pandas).
Ruff Black PytestPython est un langage interprété (pas compilé au sens C++/Java), haut niveau, et multi-plateforme. Il est célèbre pour sa syntaxe claire, lisible (presque de l'anglais) et sa philosophie "Batteries Included" (une bibliothèque standard très riche).
Caractéristiques Clés
- Typage Dynamique Fort :
- Dynamique : Pas besoin de déclarer le type (x = 5, puisx = "hello"est OK). Le type est vérifié au moment de l'exécution (runtime).
- Fort : Interdit les opérations "magiques" (5 + "hello"-> lève uneTypeError, contrairement à JavaScript qui concaténerait en"5hello"). - Interprété : Le code est lu ligne par ligne par un interpréteur (le plus courant : CPython).
- Lisibilité (Indentation) : Utilise l'indentation (le "whitespace", 4 espaces par convention) pour définir les blocs de code (au lieu de
{...}), forçant un code propre.
Le "Zen of Python" (import this)
La philosophie de Python, écrite par Tim Peters. Tapez import this dans un interpréteur Python :
>>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Readability counts. ...
Syntaxe de Base
# Convention: utiliser le snake_case
user_name = "Alice"
user_age = 30
is_admin = True # Note: True/False (Majuscule)
rien = None # Le "Nul" de Python
# f-strings (formatage moderne)
print(f"User {user_name} a {user_age} ans.")
# L'Indentation (pas de '{...}')
if user_age > 18:
print("Majeur")
else:
print("Mineur")
Types Scalaires (Simples)
str: String (Chaîne). ("Hello"ou'Hello').int: Entier (123,-42).float: Flottant (3.14159).bool: Booléen (True,False).None: Le "Nul" de Python (None).
Strings (str) - Méthodes & f-strings
# f-strings (Le "must-know")
nom = "Alice"
age = 30
print(f"Bonjour {nom}, vous avez {age} ans.")
print(f"Calcul: { (age * 2) / 3 :.2f }") # f"Pi vaut: 3.14"
# Méthodes courantes
ligne = " Bonjour, ceci est un test. "
print(ligne.strip()) # "Bonjour, ceci est un test." (Enlève whitespace)
print(ligne.split(',')) # [" Bonjour", " ceci est un test. "]
print(ligne.startswith("Bonjour")) # False (à cause de l'espace)
print(ligne.strip().startswith("Bonjour")) # True
# Joindre une liste de strings
mots = ["Python", "est", "génial"]
phrase = " ".join(mots) # "Python est génial"
Slicing (Découpage)
Syntaxe [start:stop:step] (stop est *exclu*). Fonctionne sur les listes, tuples, et strings.
items = [0, 10, 20, 30, 40, 50, 60] # De l'index 1 (inclus) à 4 (exclu) print(items[1:4]) # [10, 20, 30] # Du début à l'index 3 (exclu) print(items[:3]) # [0, 10, 20] # De l'index 3 (inclus) à la fin print(items[3:]) # [30, 40, 50, 60] # Du début à la fin, un item sur 2 (step) print(items[::2]) # [0, 20, 40, 60] # Inverser une liste/string print(items[::-1]) # [60, 50, 40, 30, 20, 10, 0]
List (list) - Mutable
Collection ordonnée et **mutable** (modifiable).
ma_liste = [10, "hello"] ma_liste.append(True) # [10, "hello", True] ma_liste.pop(0) # Retire index 0 -> ["hello", True] print(ma_liste[0]) # "hello" ma_liste[0] = "world" # ["world", True]
Tuple (tuple) - Immutable
Collection ordonnée et **immutable** (non-modifiable).
mon_tuple = (10, "hello") # mon_tuple[0] = 99 # ERREUR! # Unpacking (très courant) x, y = mon_tuple # (x=10, y="hello")
Dictionnaire (dict) - Clé/Valeur
La structure de données la plus importante. (Map/HashMap).
user = {"name": "Alice", "age": 30}
print(user["name"]) # "Alice"
print(user.get("job", "N/A")) # "N/A" (défaut)
user["age"] = 31
# Itération
for key, value in user.items():
print(f"{key} -> {value}")
Set (set) - Uniques
Collection non-ordonnée d'éléments **uniques**.
ma_liste = [1, 2, 2, 3, 1]
mon_set = set(ma_liste) # {1, 2, 3}
print(2 in mon_set) # True (très rapide)
set_a = {1, 2, 3}
set_b = {3, 4, 5}
print(set_a | set_b) # Union: {1, 2, 3, 4, 5}
print(set_a & set_b) # Intersection: {3}
Addon (Stdlib) : collections
defaultdict: Undictqui ne lève jamais deKeyError.compteur = defaultdict(int)->compteur["mot"] += 1(marche même si "mot" n'existe pas, il vaut 0).namedtuple: Untupleoù l'on peut accéder aux champs par un nom.Point = namedtuple("Point", ["x", "y"])->p = Point(10, 20)->print(p.x)(affiche 10).
if / elif / else
age = 25
if age < 18:
print("Mineur")
elif age >= 65:
print("Senior")
else:
print("Majeur")
Boucle for (La boucle "foreach")
# Itérer sur une liste
fruits = ["pomme", "banane", "cerise"]
for fruit in fruits:
print(fruit)
# Pour obtenir l'index ET la valeur
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
Boucle while & break/continue
count = 0
while True:
count += 1
if count % 2 == 0:
continue # Saute les chiffres pairs
print(count)
if count >= 7:
break # Arrête la boucle
# (Affiche: 1, 3, 5, 7)
Fonctions (def, lambda, *args, **kwargs)
# 1. Fonction de base avec Type Hinting (Python 3+)
def saluer(nom: str, age: int = 30) -> str:
# (age=30 est un argument par défaut)
return f"Bonjour {nom}, tu as {age} ans."
# 2. Fonction "collectrice"
# *args: "avale" tous les arguments positionnels dans un tuple
# **kwargs: "avale" tous les arguments nommés dans un dict
def super_fonction(arg1, *args, **kwargs):
print(f"Arg1: {arg1}")
print(f"Autres args: {args}") # (ex: (10, 20))
print(f"Autres kwargs: {kwargs}") # (ex: {'ville': 'Paris'})
super_fonction("test", 10, 20, ville="Paris", job="Dev")
# 3. Fonction Anonyme (lambda)
# (Utile pour le tri, map, filter)
ma_liste = [{"nom": "Alice", "age": 30}, {"nom": "Bob", "age": 20}]
ma_liste.sort(key=lambda item: item["age"])
Attraper (try/except)
mon_dict = {"cle": "valeur"}
try:
x = mon_dict["cle_absente"] # Lève une KeyError
except KeyError as e:
print(f"Erreur attrapée: La clé n'existe pas ! ({e})")
x = None
except Exception as e:
print(f"Erreur inconnue: {e}")
else:
print("Accès au dict réussi.")
finally:
print("Fin du bloc try (s'exécute toujours).")
Lever (raise)
def set_age(age):
if not isinstance(age, int):
raise TypeError(f"L'âge doit être un entier, reçu: {type(age)}")
if age < 0:
raise ValueError("L'âge ne peut pas être négatif.")
try:
set_age("vingt")
except (TypeError, ValueError) as e:
print(e) # "L'âge doit être un entier, reçu: <class 'str'>"
Le code "Pythonic" est une façon d'écrire du code qui est "idiomatique", lisible, et qui utilise les forces du langage. La "List Comprehension" en est l'exemple parfait. C'est une façon de créer une liste en une seule ligne lisible.
1. List Comprehension [ ... ]
Objectif : Créer une liste des carrés des 10 premiers chiffres pairs.
Méthode "Classique" (Loop)
carres_pairs = []
for i in range(10):
if i % 2 == 0:
carres_pairs.append(i * i)
Méthode "Pythonic" (Comprehension)
carres_pairs = [i * i for i in range(10) if i % 2 == 0] # Syntaxe: # [ (ce que je veux) for (item) in (iterable) if (condition) ]
2. Dict & Set Comprehensions { ... }
# Dict Comprehension
# {clé: valeur for ...}
carres_dict = {i: i * i for i in range(5)}
# Résultat: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Set Comprehension
ma_liste = [1, 2, 2, 3, 1]
mon_set = {x for x in ma_liste}
# Résultat: {1, 2, 3}
3. Generator Expression ( ... ) & yield
Si la liste est immense (ex: 1 milliard), une "list comprehension" va saturer la RAM. On utilise une "Generator Expression" (avec (...)). Elle ne calcule les valeurs qu'à la demande (lazy).
# Ceci ne calcule RIEN, c'est un "générateur"
carres_gen = (i * i for i in range(1000000000))
# 'yield' est la façon de créer un générateur dans une fonction
def gen_carres(n):
for i in range(n):
yield i * i # "Pause" et renvoie la valeur
# Le calcul se fait ici, un par un
for c in carres_gen:
print(c)
if c > 100:
break # Ne calcule pas les 999 millions restants
4. Context Manager (with open)
Ne *jamais* gérer des fichiers manuellement (f.open(), f.close()). La "bonne" façon est d'utiliser with, qui gère le finally (fermeture) pour vous.
# La façon "Pythonic" de gérer les ressources
with open("mon_fichier.txt", "r") as f:
contenu = f.read()
# (Ici, 'f' est automatiquement fermé, même si une erreur a eu lieu)
Python est un langage orienté objet (POO). Tout est objet (même les fonctions).
Classe, __init__, et self
self est l'équivalent du this (en Java/JS). C'est le premier argument de *chaque* méthode d'instance. __init__ est le constructeur.
# 1. Définition de la classe
class Utilisateur:
# 2. Constructeur (lancé à la création)
def __init__(self, nom, email):
# 3. 'self' fait référence à l'instance
self.nom = nom
self.email = email
self.est_actif = True
# 4. Méthode d'instance
def saluer(self):
return f"Bonjour, je suis {self.nom}."
# 5. Instanciation
user_1 = Utilisateur("Alice", "alice@mail.com")
print(user_1.nom) # "Alice"
Héritage & super()
# 1. La classe "Enfant" hérite de "Utilisateur"
class Admin(Utilisateur):
def __init__(self, nom, email, permissions):
# 2. On appelle le constructeur parent (Utilisateur)
super().__init__(nom, email)
self.permissions = permissions
# 3. On "override" (surcharge) la méthode parent
def saluer(self):
return f"[ADMIN] Bonjour, je suis {self.nom}."
Méthodes Magiques (Dunder)
Méthodes spéciales (__nom__) qui définissent le comportement de l'objet.
class Livre:
def __init__(self, titre, auteur):
self.titre = titre
self.auteur = auteur
# 'str(livre)' ou 'print(livre)'
def __str__(self):
return f"'{self.titre}' par {self.auteur}"
# 'repr(livre)' (Pour le débug)
def __repr__(self):
return f"Livre(titre='{self.titre}')"
# 'len(livre)'
def __len__(self):
return len(self.titre)
livre = Livre("Dune", "F. Herbert")
print(livre) # "'Dune' par F. Herbert"
Les "décorateurs" (@) sont des "addons" pour les fonctions. Ce sont des fonctions qui "enveloppent" d'autres fonctions pour modifier leur comportement.
@staticmethod vs @classmethod
| Décorateur | 1er Argument | Description |
|---|---|---|
| Méthode d'instance (défaut) | self | A accès à l'instance (self.nom). |
@classmethod | cls | A accès à la *Classe* (cls.objects.all()). N'a pas accès à l'instance (self). |
@staticmethod | (Aucun) | N'a accès *ni* à l'instance (self) *ni* à la classe (cls). C'est juste une fonction utilitaire rangée dans la classe. |
@property (Getters & Setters "Pythonic")
La "mauvaise" façon (style Java) est user.get_email(). La façon "Pythonic" est d'utiliser @property pour qu'une méthode se comporte comme un attribut.
class Utilisateur:
def __init__(self, prenom, nom):
self._email = f"{prenom}.{nom}@mail.com"
@property
def email(self):
return self._email # Getter
@email.setter
def email(self, nouvelle_valeur):
self._email = nouvelle_valeur # Setter
@dataclass (Python 3.7+)
Écrire __init__ et __repr__ est répétitif. Ce décorateur le fait pour vous.
Avant (Classique)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
Après (Dataclass)
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
Python a une cadence de sortie annuelle (en octobre). Les versions "modernes" (post 3.5) ont ajouté des fonctionnalités majeures. La transition Python 2 -> 3 (2008) a été un événement majeur, mais Python 2 est mort et n'est plus supporté depuis 2020.
| Version | Date Sortie | Nouveautés Clés |
|---|---|---|
| 3.5 | Sep 2015 | async / await (AsyncIO), Opérateur "unpacking" ** dans les dicts. |
| 3.6 | Dec 2016 | f-Strings (formatage littéral), Dictionnaires ordonnés (par défaut). |
| 3.7 | Juin 2018 | @dataclasses (POO simplifiée), async/await deviennent mots-clés. |
| 3.8 | Oct 2019 | "Walrus Operator" (:=) (assignation dans une expression). |
| 3.9 | Oct 2020 | Union de dict (|), str.removeprefix(), Type Hinting natif (list[int]). |
| 3.10 | Oct 2021 | match / case (Structural Pattern Matching), ExceptionGroup. |
| 3.11 | Oct 2022 | "Faster CPython" (Performances +10-60%), tomllib (pour .toml). |
| 3.12 | Oct 2023 | Messages d'erreur améliorés, support de type (Type Hinting). |
| 3.13 | Oct 2024 | Améliorations du JIT (expérimental), Loop de asyncio ré-écrit en C. |
match / case (Python 3.10+)
Le "switch/case" de Python, mais en beaucoup plus puissant.
def http_status(status):
match status:
case 200:
return "OK"
case 404:
return "Not Found"
case 418:
return "I'm a teapot"
case 400 | 401 | 403: # (Pattern "OU")
return "Client Error"
case 500 | 501 | 502 | 503:
return "Server Error"
case _: # (Wildcard)
return "Unknown"
Modules, Packages & import
- Module : Un simple fichier Python (ex:
utils.py). - Package : Un dossier de modules (ex:
mon_projet/) qui contient un fichier spécial__init__.py(qui peut être vide).
# 1. Importer un module entier (de la bibliothèque standard) import os print(os.getcwd()) # Affiche le dossier courant # 2. Importer un objet spécifique d'un module from datetime import datetime, timedelta print(datetime.now() + timedelta(days=1)) # 3. Importer son propre code # (si mon_app/utils.py existe) from mon_app.utils import ma_fonction # 4. Importer avec un alias (TRÈS courant en Data Science) import pandas as pd df = pd.DataFrame()
pip (Package Manager) & venv (Isolation)
Problème : Projet A a besoin de django==3.0. Projet B a besoin de django==4.0. On ne peut pas les installer "globalement".
Solution : venv (Virtual Environment). Crée un "silo" (dossier) avec une installation Python isolée pour *chaque* projet.
Workflow (Cheat-sheet) :
# 1. Créer l'environnement virtuel (dans le dossier 'venv') $ python3 -m venv venv # 2. L'ACTIVER (change le shell) $ source venv/bin/activate (venv) $ <-- Le prompt change ! # 3. Installer des packages (uniquement dans 'venv') (venv) $ pip install requests (venv) $ pip install django # 4. Geler les dépendances (venv) $ pip freeze > requirements.txt # 5. (Sur une autre machine) Installer depuis le fichier (venv) $ pip install -r requirements.txt # 6. Quitter l'environnement (venv) $ deactivate $
Python est un pilier majeur du développement web back-end, avec trois frameworks dominants et un outil essentiel pour les tâches de fond.
| Framework | Philosophie | Cas d'usage |
|---|---|---|
Django (pip install django) | "Batteries Included" (MVT). Fournit *tout* : ORM, Admin, Auth, Routage. Architecture MVT (Model-View-Template). | Applications complexes, CMS, ERPs. (Ex: Instagram, Pinterest). |
Flask (pip install flask) | "Micro-framework". Ne fournit que le routage et le templating (Jinja2). Vous apportez vos propres outils (ex: SQLAlchemy pour l'ORM). | Petites APIs, microservices, projets où la flexibilité est reine. (Ex: Netflix [partiellement]). |
FastAPI (pip install fastapi) | "Moderne & Rapide". Basé sur AsyncIO ( async/await) pour haute performance. Auto-génère la documentation (OpenAPI) grâce au Type Hinting (Pydantic). | APIs modernes, microservices, applications I/O intensives (où l'on attend des BDD/APIs). |
Celery (pip install celery) | Gestionnaire de Tâches Asynchrones. Permet à Django/Flask de déporter des tâches longues (emails, calculs) hors de la requête. | Envoyer un email sans bloquer l'utilisateur. (Voir le guide "Celery"). |
SQLAlchemy (pip install SQLAlchemy) | Le "vrai" ORM. Une boîte à outils BDD agnostique (Core) et un ORM (Declarative). Utilisé par Flask et FastAPI. | Tout ce qui touche à une BDD SQL de façon complexe. |
C'est le *deuxième* pilier majeur de Python (et peut-être le plus grand aujourd'hui). Python est le langage n°1 de la Data Science et de l'IA.
| Librairie | Description | Exemple de code |
|---|---|---|
| NumPy (Numerical Python) | La fondation. Fournit des tableaux (Arrays ndarray) N-dimensionnels ultra-rapides (écrits en C). | import numpy as np |
| Pandas | L'outil d'analyse de données. Fournit le DataFrame (un "Excel" en code). Parfait pour lire/écrire des CSV, agréger, nettoyer. | import pandas as pd |
| Matplotlib / Seaborn | La bibliothèque "historique" de plotting (graphiques). Seaborn est un "wrapper" par-dessus pour de plus beaux graphiques. | import matplotlib.pyplot as plt |
| Jupyter (Notebooks) | Un environnement web interactif (.ipynb) pour mélanger code, texte (Markdown) et graphiques. L'outil n°1 des data scientists. | $ jupyter notebook |
| Scikit-learn | La boîte à outils n°1 du Machine Learning "classique". (Régression, Classification, Clustering). | from sklearn.svm import SVC |
| PyTorch (Facebook) & TensorFlow (Google) | Les deux géants du Deep Learning (Réseaux de neurones). | import torch |
Ces outils ("plugins" ou "addons") ne font pas partie du langage, mais sont *essentiels* à tout projet Python professionnel pour garantir la qualité, la maintenabilité et la reproductibilité.
Outils de Qualité de Code (Linters & Formatters)
| Outil | Type | Description | Commande |
|---|---|---|---|
| Ruff | Linter + Formatter | Le nouveau standard (écrit en Rust). 100x plus rapide que Flake8+Black+isort réunis. | $ ruff check . --fix |
| Black | Formatter | Le "formateur d'opinion". Il ré-écrit votre code pour qu'il soit *parfaitement* formaté. "Vous pouvez avoir n'importe quel style, tant que c'est Black." | $ black . |
| Flake8 | Linter (Legacy) | L'ancien standard. Analyse statique qui "crie" si vous ne respectez pas les conventions (PEP 8) ou si vous avez des bugs. | $ flake8 . |
| MyPy | Type Checker | Analyse vos "Type Hints" (nom: str) et trouve les incohérences (ex: "Tu passes un int à une fonction qui attend un str"). | $ mypy . |
Outils de Test & Dépendance
| Outil | Type | Description | Commande |
|---|---|---|---|
| Pytest | Test Runner | Le standard pour les tests unitaires/intégration. Plus simple et plus puissant que unittest (stdlib). | $ pytest |
| Poetry (ou PDM) | Gestionnaire | Alternative moderne à pip + venv + requirements.txt. Gère tout (dépendances, venv, build) dans un seul pyproject.toml. | $ poetry install |
Librairies "Plugins" Incontournables (PyPI)
- Requests "HTTP for Humans". Remplace
urllib(stdlib) pour faire des appels API/HTTP. - Pandas Le pilier de la Data Science (DataFrames).
- Pillow (PIL) La bibliothèque n°1 pour la manipulation d'images (resize, crop, filtres).
- python-dotenv Permet de charger des variables d'environnement (ex: clés API) depuis un fichier
.env. - BeautifulSoup4 Le "parser" HTML/XML n°1 pour le web scraping.
