Aller au contenu principal

Les Listes en Python

Creer une liste

Une liste est une collection ordonnee et modifiable d'elements. En Python, les listes peuvent contenir des elements de types differents.

# Liste vide
vide = []
aussi_vide = list()

# Liste de nombres
notes = [15, 12, 18, 9, 14]

# Liste de chaines
fruits = ["pomme", "banane", "cerise"]

# Liste mixte (possible mais rarement utile)
melange = [42, "bonjour", True, 3.14]

# A partir d'un range
cinq_premiers = list(range(5)) # [0, 1, 2, 3, 4]
pairs = list(range(0, 10, 2)) # [0, 2, 4, 6, 8]

Acceder aux elements

Indexation positive

Les elements sont indexes a partir de 0 :

fruits = ["pomme", "banane", "cerise", "datte"]

print(fruits[0]) # pomme (premier)
print(fruits[1]) # banane
print(fruits[2]) # cerise
print(fruits[3]) # datte (dernier, index = longueur - 1)

Indexation negative

Les indices negatifs partent de la fin : -1 est le dernier element, -2 l'avant-dernier, etc.

fruits = ["pomme", "banane", "cerise", "datte"]

print(fruits[-1]) # datte (dernier)
print(fruits[-2]) # cerise (avant-dernier)
print(fruits[-4]) # pomme (premier depuis la fin)

Slicing (decoupage)

Le slicing permet d'extraire une sous-liste avec la syntaxe liste[debut:fin:pas]. La borne fin est exclue.

nombres = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(nombres[2:5]) # [2, 3, 4] (indices 2, 3, 4)
print(nombres[:4]) # [0, 1, 2, 3] (du debut a l'index 3)
print(nombres[6:]) # [6, 7, 8, 9] (de l'index 6 a la fin)
print(nombres[::2]) # [0, 2, 4, 6, 8] (un sur deux)
print(nombres[1::2]) # [1, 3, 5, 7, 9] (impairs)
print(nombres[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (inverse)
print(nombres[2:8:3]) # [2, 5] (de 2 a 7, pas de 3)

Modifier une liste

Les listes sont mutables : on peut changer leurs elements directement.

notes = [12, 15, 9, 18, 11]

# Modifier un element
notes[2] = 14
print(notes) # [12, 15, 14, 18, 11]

# Modifier une plage (slice)
notes[1:3] = [17, 16]
print(notes) # [12, 17, 16, 18, 11]

Methodes des listes

Python fournit de nombreuses methodes pour manipuler les listes.

Ajouter des elements

fruits = ["pomme", "banane"]

fruits.append("cerise") # ajoute a la fin
print(fruits) # ["pomme", "banane", "cerise"]

fruits.insert(1, "abricot") # insere a l'index 1
print(fruits) # ["pomme", "abricot", "banane", "cerise"]

fruits.extend(["datte", "figue"]) # ajoute plusieurs elements
print(fruits) # ["pomme", "abricot", "banane", "cerise", "datte", "figue"]

Supprimer des elements

fruits = ["pomme", "banane", "cerise", "banane"]

fruits.remove("banane") # supprime la PREMIERE occurrence
print(fruits) # ["pomme", "cerise", "banane"]

dernier = fruits.pop() # supprime et retourne le dernier
print(dernier) # "banane"
print(fruits) # ["pomme", "cerise"]

deuxieme = fruits.pop(0) # supprime et retourne l'element a l'index 0
print(deuxieme) # "pomme"

fruits.clear() # vide completement la liste
print(fruits) # []

Trier et inverser

nombres = [3, 1, 4, 1, 5, 9, 2, 6]

nombres.sort() # tri en place (modifie la liste)
print(nombres) # [1, 1, 2, 3, 4, 5, 6, 9]

nombres.sort(reverse=True) # tri inverse
print(nombres) # [9, 6, 5, 4, 3, 2, 1, 1]

nombres.reverse() # inverse l'ordre en place
print(nombres) # [1, 1, 2, 3, 4, 5, 6, 9]

Rechercher

fruits = ["pomme", "banane", "cerise", "banane"]

idx = fruits.index("banane") # indice de la PREMIERE occurrence
print(idx) # 1

nb = fruits.count("banane") # nombre d'occurrences
print(nb) # 2

Copier

original = [1, 2, 3]
copie = original.copy() # copie superficielle

copie.append(4)
print(original) # [1, 2, 3] (non modifie)
print(copie) # [1, 2, 3, 4]

Fonctions built-in pour les listes

notes = [12, 15, 9, 18, 11, 14]

print(len(notes)) # 6 - nombre d'elements
print(min(notes)) # 9 - valeur minimale
print(max(notes)) # 18 - valeur maximale
print(sum(notes)) # 79 - somme des elements

moyenne = sum(notes) / len(notes)
print(round(moyenne, 2)) # 13.17

Listes en comprehension

Les listes en comprehension permettent de creer des listes de maniere concise et lisible.

# Syntaxe : [expression for element in iterable if condition]

# Sans condition
carres = [x ** 2 for x in range(6)]
print(carres) # [0, 1, 4, 9, 16, 25]

# Avec condition
pairs = [x for x in range(10) if x % 2 == 0]
print(pairs) # [0, 2, 4, 6, 8]

# Transformation de chaines
noms = ["alice", "bob", "claire"]
majuscules = [nom.upper() for nom in noms]
print(majuscules) # ["ALICE", "BOB", "CLAIRE"]

# Filtrer et transformer
notes = [12, 15, 9, 18, 11, 14]
bonnes_notes = [n for n in notes if n >= 12]
print(bonnes_notes) # [12, 15, 18, 14]

Comparaison avec la boucle equivalente :

# Avec boucle
carres = []
for x in range(6):
carres.append(x ** 2)

# Avec comprehension (equivalent, plus concis)
carres = [x ** 2 for x in range(6)]

Listes imbriquees (matrices 2D)

Une liste peut contenir d'autres listes, ce qui permet de representer des matrices ou des tableaux 2D :

matrice = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]

# Acces : matrice[ligne][colonne]
print(matrice[0][0]) # 1 (ligne 0, colonne 0)
print(matrice[1][2]) # 6 (ligne 1, colonne 2)
print(matrice[2][1]) # 8 (ligne 2, colonne 1)

# Parcourir une matrice
for ligne in matrice:
for valeur in ligne:
print(valeur, end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9

Decomposition (unpacking)

On peut "decompacter" une liste en plusieurs variables :

coordonnees = [48.8566, 2.3522]
latitude, longitude = coordonnees
print(latitude) # 48.8566
print(longitude) # 2.3522

# Unpacking avec *rest
nombres = [1, 2, 3, 4, 5]
premier, *reste = nombres
print(premier) # 1
print(reste) # [2, 3, 4, 5]

*debut, dernier = nombres
print(debut) # [1, 2, 3, 4]
print(dernier) # 5

premier, *milieu, dernier = nombres
print(premier) # 1
print(milieu) # [2, 3, 4]
print(dernier) # 5

Verifier l'appartenance

fruits = ["pomme", "banane", "cerise"]

print("banane" in fruits) # True
print("mangue" in fruits) # False
print("mangue" not in fruits) # True

# Utilisation dans un if
if "cerise" in fruits:
print("On a des cerises !")

Copie superficielle vs copie profonde

Attention a la copie des listes imbriquees :

import copy

# Assignation : pas une copie !
a = [1, 2, 3]
b = a # b pointe vers le MEME objet
b.append(4)
print(a) # [1, 2, 3, 4] (a aussi modifie !)

# Copie superficielle : OK pour listes simples
a = [1, 2, 3]
b = a.copy() # ou b = a[:] ou b = list(a)
b.append(4)
print(a) # [1, 2, 3] (a non modifie)

# Copie superficielle INSUFFISANTE pour listes imbriquees
a = [[1, 2], [3, 4]]
b = a.copy()
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]] (a aussi modifie !)

# Copie profonde : independance totale
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0].append(99)
print(a) # [[1, 2], [3, 4]] (a non modifie)

Trier avec une cle personnalisee

sorted() retourne une nouvelle liste triee sans modifier l'originale. Le parametre key accepte une fonction :

etudiants = [("Alice", 17), ("Bob", 15), ("Claire", 19), ("David", 16)]

# Trier par note (index 1)
par_note = sorted(etudiants, key=lambda e: e[1])
print(par_note)
# [('Bob', 15), ('David', 16), ('Alice', 17), ('Claire', 19)]

# Trier par nom (index 0)
par_nom = sorted(etudiants, key=lambda e: e[0])
print(par_nom)
# [('Alice', 17), ('Bob', 15), ('Claire', 19), ('David', 16)]

# Trier des chaines sans tenir compte de la casse
mots = ["Banane", "abricot", "Cerise", "datte"]
tries = sorted(mots, key=lambda m: m.lower())
print(tries) # ['abricot', 'Banane', 'Cerise', 'datte']

Exercices pratiques

Exercice 1 : Creer une liste et acceder aux elements

Bonne pratique - Index negatif

Utilisez liste[-1] plutot que liste[len(liste)-1] pour acceder au dernier element. C'est plus lisible et moins sujet aux erreurs. De meme, liste[-2] pour l'avant-dernier est idiomatique en Python.


Exercice 2 : Modifier une liste avec append et pop

Bonne pratique - pop(0) vs deque

pop(0) sur une liste est lent (O(n)) car Python doit decaler tous les elements. Si vous utilisez frequemment des ajouts/suppressions en debut de liste, utilisez collections.deque qui est optimise pour ca (O(1)).


Exercice 3 : Slicing

Bonne pratique - Slicing

Rappelez-vous que liste[debut:fin] inclut debut mais exclut fin. Pour copier une liste entiere, liste[:] est un raccourci pratique. Le slice [::-1] est la facon pythonique d'inverser une liste (ou une chaine).


Exercice 4 : Liste en comprehension (carres)

Bonne pratique - Comprehensions lisibles

Les listes en comprehension sont excellentes pour des transformations simples. Si votre comprehension devient trop longue ou complexe (plus d'une condition, plusieurs boucles imbriquees), preferez une boucle for classique pour la lisibilite. La regle : si ca ne tient pas sur une ligne claire, utilisez une boucle.


Exercice 5 : Trier une liste

Bonne pratique - sort() vs sorted()

Utilisez sort() (methode, modifie en place) quand vous n'avez plus besoin de l'ordre original. Utilisez sorted() (fonction built-in) quand vous voulez conserver la liste originale ou trier un iterable quelconque. sorted() retourne toujours une nouvelle liste.


Exercice 6 : Trouver un element avec index()

Bonne pratique - Verifier avant index()

index() leve une ValueError si l'element n'est pas trouve. Avant d'appeler index(), verifiez d'abord la presence avec if valeur in liste. Alternativement, utilisez un bloc try/except ValueError pour gerer le cas ou l'element est absent.


Quiz de revision


Quel est l'index du dernier element d'une liste de 5 elements ?


Que retourne liste[2:5] si liste = [0, 1, 2, 3, 4, 5, 6] ?


Quelle methode supprime ET retourne un element d'une liste ?


Que fait b = a si a est une liste ?


Quelle est la syntaxe correcte d'une liste en comprehension pour les nombres pairs de 0 a 9 ?


Une solution