Les listes sont muables☘
Modifier un élément☘
Contrairement aux chaînes de caractères et aux tuples, les listes sont muables. Cela signifie que l'on peut changer un élément de la liste sans changer d'objet liste.
On peut voir l'objet conteneur (liste, tuple, chaîne) comme une bouteille:
- Si la bouteille est une chaîne ou un tuple, on voit ce qu'il y a dans la bouteille mais elle est bien scellée et il est impossible d'en modifier son contenu. Pour avoir un autre contenu, on doit remplir une autre bouteille.
- Si la bouteille est une liste, on peut voir ce qu'il y a dans la bouteille et la bouteille reste ouverte: on peut modifier une partie de son contenu, ou ajouter du contenu ou encore enlever du contenu.
Important
En python:
- les objets de type str, de type tuple, de type int, de type float sont des immuables.
- Les objets de type list sont muables.
Pour constater que le conteneur de la liste n'est pas modifié même lorsque le contenu est modifié,
on peut utiliser la fonction id
qui donne un identifiant
d'un objet python. On peut considérer que cet id est l'adresse en mémoire de l'objet.
On constate dans le code ci-dessous que l'objet liste
reste le même après avoir modifié l'un de ses éléments (seuls les objets définissant
son contenu ont changé):
>>> tab = [3, 4, 5, 6]
>>> id(tab)
139779891177608
>>> tab[1] = 42
>>> tab
[3, 42, 5, 6]
>>> id(tab)
139779891177608
Schéma après la ligne
tab = [3, 4, 5, 6]
Schéma après la ligne
tab[1] = 42
L'objet tab
est le même, mais son contenu a été modifié:
l'objet ciblé par tab[1]
a changé.
Plusieurs étiquettes sur une liste☘
Quel sera le contenu de a, de b, de c en dernière ligne? Expliquer.
>>> a = [2, 3, 4, 5, 6]
>>> b = a
>>> c = [2, 3, 4, 5, 6]
>>> b[-1] = 666
>>> a[0] = 42
Réponse
>>> a = [2, 3, 4, 5, 6]
>>> b = a
>>> c = [2, 3, 4, 5, 6]
>>> b[-1] = 666
>>> a[0] = 42
>>> a
[42, 3, 4, 5, 666]
>>> b
[42, 3, 4, 5, 666]
>>> c
[2, 3, 4, 5, 6]
- Après les lignes:
>>> a = [2, 3, 4, 5, 6]
>>> b = a
>>> c = [2, 3, 4, 5, 6]
on dispose de deux objets de type list distincts. L'un porte deux étiquettes (a et b), l'autre porte une étiquette (c).
- Après la ligne
>>> b[-1] = 666
on est dans la situation suivante:
- Après la ligne
>>> a[0] = 42
on est dans la situation suivante:
Pour vérifier que a et b désigne la même bouteille, on peut utiliser is
:
>>> a is b # pour vérifier que a et b sont deux étiquettes du même objet
True
>>> a == b # pour vérifier que a et b ont les mêmes contenus
True
Pour vérifier que deux listes ont même contenu mais sont des listes (conteneurs) différentes:
>>> d = [2, 3]
>>> e = [2, 3]
>>> d == e # True car les listes d et e ont même contenu
True
>>> d is e # False car d et e sont des étiquettes ciblant des objets différents
False
Note
Sur la doc python.
Ajouter un élément☘
Les chaînes et les tuples étant immuables, on ne peut pas modifier l'un de leurs éléments, ni en ajouter un sans créer un nouveau conteneur.
Par contre, on peut ajouter un élément à une liste sans changer la liste (on continue de remplir la bouteille sans changer de bouteille).
Pour ajouter un élément à une liste (en fin de liste), on utilise la méthode append
:
>>> a = [2, 3, 4]
>>> id(a)
139779891299912
>>> a.append(42)
>>> a
[2, 3, 4, 42]
>>> id(a)
139779891299912
- Après la première ligne
>>> a = [2, 3, 4]
on a la situation suivante:
- Après la ligne
a.append(42)
l'objet désigné par a
est le même objet mais avec un élément de plus:
Exercice☘
Écrire un code possible pour le corps de la fonction suivante:
def moyenner(tab):
"""
tab -- liste de flottants
remplace chaque élément de tab par la moyenne des éléments de tab
(la fonction ne renvoie rien,
elle agit en place sur la liste passée en argument)
"""
Un code
def moyenner(tab):
"""
tab -- liste de flottants
remplace chaque élément de tab par la moyenne des éléments de tab
"""
somme = 0
for element in tab: somme += element
moyenne = somme/len(tab)
for indice in range(len(tab)): tab[indice] = moyenne
Exemple d'utilisation: fichier ipynb (version html)
Détails
Détaillons un peu ce qu'il se passe sur les variables avec l'essai suivant.
def moyenner(tab):
"""
tab -- liste de flottants
remplace chaque élément de tab par la moyenne des éléments de tab
"""
somme = 0
for element in tab: somme += element
moyenne = somme/len(tab)
for indice in range(len(tab)): tab[indice] = moyenne
if __name__ == '__main__':
L = [3, 4, 2, 1]
moyenner(L)
print(L)
Après la ligne:
L = [3, 4, 2, 1]
on a la situation:
On appelle alors la fonction moyenner:
moyenner(L)
On a alors la situation suivante:
On exécute les lignes suivantes du corps de la fonction moyenner:
somme = 0
for element in tab: somme += element
moyenne = somme/len(tab)
On a la situation suivante:
Puis on exécute la dernière ligne du code de la fonction moyenner:
for indice in range(len(tab)): tab[indice] = moyenne
La situation devient:
On sort de la fonction: tout nom local à la fonction disparaît.
La situation:
Remarque. On a laissé la représentation d' objets créés lors de l'exécution de la fonction. Ceux qui n'ont plus d'étiquette peuvent être considérés comme ayant disparus: on n'a plus accès à ces objets puisqu'ils n'ont plus d'étiquette.
Exercice☘
Nous avons vu comment faire une copie d'une liste par compréhension:
def copier(tab):
"""
tab -- liste
renvoie une liste de même contenu que tab
>>> A = [42, 666, 1789]
>>> B = copie(A)
>>> B
[42, 666, 1789]
"""
return [element for element in tab]
Proposer un équivalent de cette fonction utilisant la méthode append
.
Un code
def copier(tab):
"""
tab -- liste
renvoie une liste de même contenu que tab
>>> A = [42, 666, 1789]
>>> B = copie(A)
>>> B
[42, 666, 1789]
"""
nvTab = []
for element in tab:
nvTab.append(element)
return nvTab
Schémas
Voyons un peu le détail avec l'appel suivant:
def copier(tab):
"""
tab -- liste
renvoie une liste de même contenu que tab
>>> A = [42, 666, 1789]
>>> B = copie(A)
>>> B
[42, 666, 1789]
"""
nvTab = []
for element in tab:
nvTab.append(element)
return nvTab
if __name__ == '__main__':
L = [3, 4, 2, 1]
T = copier(L)
print(L)
print(T)
Après la ligne:
L = [3, 4, 2, 1]
on a la situation:
On appelle alors la fonction copier (partie droite de l'instruction d'affectation en ligne 20):
copier(L)
La situation:
Puis on exécute la ligne
nvTab = []
Puis on exécute les lignes
for element in tab:
nvTab.append(element)
Enfin la fonction renvoie cette liste et on l'affecte à T: