Apprendre Python de zéro jusqu'au niveau expert : syntaxe, structures de données, POO, générateurs, décorateurs, typage, tests, async et internals du langage.
Quatre structures couvrent 95 % des besoins : list, tuple, dict, set. Choisir la bonne, c'est souvent la différence entre un script qui prend 2 secondes et un qui prend 20 minutes.
| Structure | Ordonnée | Mutable | Doublons | Recherche in |
|---|---|---|---|---|
list | oui | oui | oui | O(n) |
tuple | oui | non | oui | O(n) |
dict | oui (insertion) | oui | clés uniques | O(1) |
set | non | oui | non | O(1) |
nums = [5, 3, 8]
nums.append(1) # [5, 3, 8, 1]
nums.insert(0, 9) # [9, 5, 3, 8, 1]
nums.extend([7, 7]) # ajoute plusieurs éléments
nums.pop() # retire et renvoie le dernier
nums.remove(3) # retire la première occurrence de 3
nums.sort() # tri en place, renvoie None
trie = sorted(nums) # nouvelle liste triée
nums[1:3] # slicing
nums[::-1] # copie inverséenums.sort() renvoie None. Écrire nums = nums.sort() efface votre liste : erreur classique.
a = [[1, 2], [3, 4]]
b = a.copy() # copie superficielle
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]] — les sous-listes sont partagées
import copy
c = copy.deepcopy(a) # copie profonde, indépendanteUn tuple est une liste immuable. On l'utilise pour des données de taille fixe dont chaque position a un sens.
point = (3, 4)
x, y = point # unpacking
rgb = 255, 128, 0 # les parenthèses sont optionnelles
singleton = (1,) # la virgule fait le tuple, pas les parenthèsesImmuable signifie hashable (si ses éléments le sont) : un tuple peut servir de clé de dictionnaire, une liste non.
Pour des tuples lisibles, NamedTuple :
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float
p = Point(3, 4)
p.x # 3La structure la plus importante de Python. Les objets, les modules, les classes reposent en interne sur des dictionnaires.
user = {"nom": "Ada", "age": 36}
user["email"] = "ada@example.com"
user["age"] += 1
del user["email"]
user["ville"] # KeyError
user.get("ville") # None
user.get("ville", "Inconnue") # 'Inconnue'
"nom" in user # True
for cle, valeur in user.items():
print(cle, valeur)
fusion = user | {"role": "admin"} # Python 3.9+setdefault et defaultdict évitent les tests d'existence :
from collections import defaultdict
mots = "le chat et le chien et le rat".split()
par_lettre = defaultdict(list)
for mot in mots:
par_lettre[mot[0]].append(mot)
# {'l': ['le', 'le', 'le'], 'c': ['chat', 'chien'], 'e': ['et', 'et'], 'r': ['rat']}Et pour compter, Counter :
from collections import Counter
Counter(mots).most_common(2) # [('le', 3), ('et', 2)]Collection non ordonnée d'éléments uniques. Idéal pour dédoublonner et tester l'appartenance.
tags = {"python", "web", "python"} # {'python', 'web'}
vide = set() # {} crée un dict, pas un set
a = {1, 2, 3}
b = {2, 3, 4}
a | b # union {1, 2, 3, 4}
a & b # intersection {2, 3}
a - b # différence {1}
a ^ b # symétrique {1, 4}Quand j'ai dû comparer deux exports de 200 000 emails, passer de if email in liste à if email in ensemble a fait tomber le temps de plusieurs minutes à moins d'une seconde. C'est la différence entre O(n) et O(1) multipliée par 200 000.
Les compréhensions construisent une collection en une expression. Elles sont plus rapides et plus lisibles qu'une boucle append.
carres = [n ** 2 for n in range(10)]
pairs = [n for n in range(20) if n % 2 == 0]
longueurs = {mot: len(mot) for mot in ["python", "go"]}
initiales = {nom[0] for nom in ["Ada", "Alan", "Linus"]}
matrice = [[i * j for j in range(3)] for i in range(3)]
aplati = [x for ligne in matrice for x in ligne]Règle perso : au-delà d'un for et d'un if, je repasse à une boucle classique.
premier, *milieu, dernier = [1, 2, 3, 4, 5]
fusion = [*liste_a, *liste_b]
config = {**defaults, **overrides}| Outil | Usage |
|---|---|
deque | file à deux bouts, append/popleft en O(1) |
Counter | comptage d'occurrences |
defaultdict | valeur par défaut automatique |
OrderedDict | ordre + move_to_end, utile pour un cache LRU |
ChainMap | recherche dans plusieurs dicts successifs |
list.pop(0) est en O(n) car tous les éléments se décalent. Pour une file d'attente, deque est obligatoire.
from collections import Counter
import re
texte = open("livre.txt", encoding="utf-8").read().lower()
mots = re.findall(r"\b[a-zàâçéèêëîïôûùüÿœ]{4,}\b", texte)
top = Counter(mots).most_common(10)
for rang, (mot, n) in enumerate(top, start=1):
print(f"{rang:2}. {mot:<15} {n}")L'expression régulière filtre les mots de 4 lettres et plus. Pour décortiquer ce genre de motif, voir le guide des expressions régulières.
Le bon réflexe : liste pour une séquence, dict pour une correspondance clé → valeur, set pour l'unicité et les recherches rapides, tuple pour un enregistrement fixe. Quand un script rame, la première question à se poser est laquelle de ces structures a été mal choisie.