Listes et séquences mutables
Une list Python est une séquence mutable de références d'objets. Elle préserve l'ordre, accepte des types de valeurs mélangés et prend en charge l'indexage entier et les tranches.
names = ["Ada", "Grace", "Linus"]
first = names[0]
last = names[-1]
middle = names[1:2] # une nouvelle liste par copie superficielle
Mutation et alias
Une affectation lie un autre nom à la même liste ; elle ne la copie pas.
original = [[1], [2]]
alias = original
shallow = original.copy()
alias.append([3]) # modifie aussi original
shallow[0].append(9) # la liste imbriquée reste partagée
N'utilisez copy.deepcopy que si la duplication récursive de tout le graphe d'objets correspond réellement au modèle de responsabilité attendu. Une responsabilité claire est généralement plus facile à raisonner qu'une copie profonde défensive.
Les mutations courantes ont des contrats distincts :
items.append(value) # une valeur à la fin
items.extend(iterable) # toutes les valeurs d'un itérable
items.insert(index, value)
last = items.pop() # supprimer et renvoyer
items.remove(value) # première valeur égale ; ValueError si absente
items[1:3] = replacements # une affectation de tranche peut changer la longueur
Ne modifiez pas structurellement une liste pendant son parcours, sauf intention explicite. Parcourez une copie ou construisez un nouveau résultat.
Compréhensions et générateurs
Utilisez une compréhension de liste pour une transformation ou un filtre lisible :
squares = [number * number for number in numbers if number >= 0]
Une compréhension construit toute la liste. Employez une expression génératrice lorsque les valeurs peuvent être consommées paresseusement :
total = sum(number * number for number in numbers)
Évitez les compréhensions profondément imbriquées ; une boucle ordinaire communique plus clairement les changements d'état en plusieurs étapes.
Coûts typiques
CPython représente les listes par des tableaux redimensionnables de références : c'est un détail d'implémentation, pas une disposition mémoire imposée à toute implémentation Python. Le tableau décrit ce modèle, avec des comparaisons d'éléments de coût constant ; des méthodes d'égalité personnalisées peuvent ajouter du travail.
Utilisez collections.deque pour les opérations fréquentes aux deux extrémités. Employez un set ou un dict lorsque l'appartenance ou la recherche par clé domine. Un tuple exprime une séquence fixe, mais son immutabilité ne rend pas immuables les objets référencés.
Répétition et résultats des mutations
Les contrats des séquences précisent que la répétition répète des références, sans copier les objets imbriqués :
rows = [[0] * 2] * 3
rows[0][0] = 9
assert rows == [[9, 0], [9, 0], [9, 0]]
independent = [[0] * 2 for _ in range(3)]
independent[0][0] = 9
assert independent == [[9, 0], [0, 0], [0, 0]]
numbers = [3, 1, 2]
assert sorted(numbers) == [1, 2, 3]
assert numbers == [3, 1, 2]
assert numbers.sort() is None
assert numbers == [1, 2, 3]
alias = numbers
numbers += [4]
assert alias == [1, 2, 3, 4]
numbers = numbers + [5]
assert alias == [1, 2, 3, 4]
append, extend, reverse et sort modifient la liste et renvoient None ;
n'écrivez pas numbers = numbers.sort(). sorted accepte tout itérable et renvoie
une nouvelle liste. Les deux tris sont stables : des clés égales conservent leur
ordre relatif initial. Utilisez key= pour sélectionner une propriété comparable
si les éléments eux-mêmes ne peuvent pas être ordonnés.
Indexer une liste vide ou appeler son pop() lève IndexError ; une tranche
comme items[:10] ramène ses bornes aux limites. del items[index] supprime par
position, tandis que remove(value) cherche la première valeur égale. Une
affectation de tranche étendue avec un pas différent de un exige autant de
remplacements que de positions sélectionnées.