Tableaux (type list
)
Cours
Un tableau est une suite ordonnée d'éléments qui peuvent être modifiés (muables1).
En Python les tableaux sont du type list
2.
Création
Un tableau est déclaré par une série de valeurs séparées par des virgules, et le tout encadré par des crochets “[ ]
”. Il contient des éléments du même type (selon le programme de 1ere3) .
Comme pour les p-uplets, ne pas confondre la virgule de séparateur d'éléments avec le point de séparateur décimal.
Il est possible de créer un tableau vide :
ou un tableau contenant un seul élément :
Fonction len()
La fonction len()
renvoie la longueur d'un tableau, c'est-à-dire le nombre d'éléments qu'il contient.
>>> animaux = ['girafe', 'tigre', 'singe', 'souris']
>>> len(animaux)
4
>>> len([1, 2, 3, 4, 5, 6, 7, 8])
8
Accès aux éléments
Comme pour les chaines de caractères et les p-uplets, les éléments d'un tableau t
sont indexés à partir de 0
jusqu'à len(t)
exclus, c'est-à-dire le dernier élément est en position len(t) - 1
. Il est possible d'accèder aux éléments par leur index entre crochets.
Le premier élément est à l'index 0.
Comme pour les p-uplets, on peut utiliser des indices négatifs, le dernier élément à l'indice -1
, l'avant-dernier -2
, etc.
L'accès à une partie d'un tableau (une « tranche ») se fait sur le modèle t[début:fin]
4 pour récupérer tous les éléments, entre les positions debut
(inclus) et fin
(exclu).
Lorsqu'aucun indice n'est indiqué à gauche ou à droite du symbole deux-points, Python prend par défaut tous les éléments depuis le début ou tous les éléments jusqu'à la fin respectivement.
>>> t = ['a', 'b', 'c', 'd', 'e', 'f']
>>> t[1:]
['b', 'c', 'd', 'e', 'f']
>>> t[:2]
['a', 'b']
>>> t[:]
['a', 'b', 'c', 'd', 'e', 'f']
Il est aussi possible de disperser, ou « déballer », un tableau en affectant tous ses éléments dans plusieurs variables :
Le mot cléin
permet de vérifier si un élément elem
est présent dans un tableau t
, elem in t
renvoie un booléen :
De façon très similaire aux p-uplets, le mot clé in
permet aussi d'écrire une boucle pour parcourir (ou «itérer») toutes les valeurs d'un tableau. Comparons à nouveau différentes méthodes pour parcourir un tableau t
:
Il faut gérer l'indice de boucle i
pour qu'il parcourt toutes les positions des valeurs de t
, c'est-à-dire l'intialiser à 0
puis l'incrémenter à chaque passage dans la boucle (i = i + 1
) jusqu'à ce qu'il dépasse len(t) - 1
. t[i]
permet d'accéder à la valeur du tableau qui se trouve à la position i
.
Avec for i in range(len(t)):
, l'indice de boucle i
prend automatiquement les valeurs allant de 0
à len(t) - 1
. t[i]
permet d'accéder à la valeur du p-uplet qui se trouve à la position i
.
La boucle for elem in t
est plus simple pour parcourir les valeurs d'un tableau, par exemple pour rechercher la plus petite ou la plus grande valeur dans ce tableau, mais elle ne permet pas d'accéder à sa position. Pour accéder à la position d'une valeur que l'on recherche, il faut utiliser les deux autres méthodes.
Modifier un tableau
Modifier un élément
À la différence des chaines de caractères et p-uplets, il est possible de modifier la valeur d'un élément dans un tableau :
>>> animaux = ['girafe', 'tigre', 'singe', 'souris']
>>> animaux[2]= "lion"
>>> animaux
['girafe', 'tigre', 'lion', 'souris']
Opérations sur tableaux
Deux opérations sont possibles, l'addition et la multiplication :
-
L'opérateur d'addition «
+
» concatène (assemble) deux tableaux. -
L'opérateur de multiplication «
*
» entre un nombre entier et une tableau duplique (répète) plusieurs fois les éléments dans un nouveau tableau.
Ajouter de nouveaux éléments
Il existe plusieurs méthodes pour ajouter des éléments à un tableau t
:
-
t.append(x)
ajoute un élémentx
à la fin d'un tableaut
. -
t.insert(i, x)
insére un élémentx
à la position donnée par l'indicei
.i
est la position de l'élément courant avant lequel l'insertion doit s'effectuer.
-
t.extend(autretableau)
étend un tableaut
en lui ajoutant tous les éléments deautretableau
.
Ne pas confondre
append
(ajouter un élément) et extend
(étendre un tableau). Si on utilise append
avec un tableau on obtient un tableau de tableaux !
Supprimer des éléments
Il existe plusieurs méthodes pour supprimer des éléments à un tableau t
:
-
t.remove(x)
supprime le premier élément dont la valeur est égale àx
. Si le tableau contient plusieurs fois la valeurx
, seule la première occurrence trouvée est supprimée : -
t.pop(i)
supprime l'élément situé à la positioni
et le renvoie en valeur de retour. Si aucune position n'est spécifiée,t.pop()
supprime et renvoie le dernier élément du tableau : -
L'instruction
Ou encore le tableau entier avec l'instructiondel
5 permet aussi de supprimer un élément du tableau :del t
, alors la variablet
n'existe plus.
D'autres méthodes bien utiles
Deux méthodes pour trier un tableau :
-
t.sort()
ordonne les éléments dans le tableau. -
t.reverse()
inverse l'ordre des éléments du tableau.
Pour trouver un élément dans un tableau :
-
t.index(x)
renvoie la position du premier élément du tableau dont la valeur égalex
. -
t.count(x)
renvoie le nombre d'éléments ayant la valeurx
dans le tableau.
Enfin, dir(list)
permet d'obtenir la liste exhaustive des méthodes disponibles pour les tableaux.
Les méthodes telles que insert()
, remove()
ou sort()
, qui ne font que modifier le tableau, ne renvoient pas de valeur (ou plutôt elles renvoient None
).
Conversion de type (cast)
Comme la fonction tuple()
, la fonction list()
prend en argument un objet séquentiel (une chaine de caractère par exemple) et renvoie le tableau correspondant :
On peut créer un tableau vide avec la fonction list() sans argument.
Nous avons déjà vu l'utilisation de la fonction range()
. Lorsqu'elle est utilisée en combinaison avec la fonction list(), on obtient une tableau d'entiers. Par exemple :
La méthode .split()
permet de découper une chaîne en tableau avec un séparateur : chaine.split(separateur)
.
>>> chaine = 'Bonjour tout le monde !'
>>> chaine.split(' ')
['Bonjour', 'tout', 'le', 'monde', '!']
Réciproquement la méthode .join()
permet de convertir un tableau en chaîne de caractères en insérant le paramètre entre les éléments du tableau: `elementSeparateur.join(t)```.
Création par compréhension
Il est possible de créer un tableau par compréhension en utilisant l'une de ces syntaxes :
-
avec une expression sur les valeurs dans un
ancien_tableau
ou d'une fonctionrange
:nouveau_tableau = [expression(i) for i in ancien_tableau] nouveau_tableau = [expression(i) for i in range(...)]
Exemple :
est equivalent à : ou avec un autre tableau : -
avec une fonction :
nouveau_tableau = [f(x) for x in ... ]
Exemple :
-
avec une condition
if
:nouveau_tableau = [expression(i) for i in ... if condition]
Exemple :
-
avec une condition
if...else
:nouveau_tableau = [expression(i) if condition else autre_expression(i) for i in ...]
(attention l'ordre est différent)Exemple :
-
avec plusieurs paramètres :
nouveau_tableau = [expression(i, j) for i in ... for j in ... if condition]
Exemples:
Tableaux de tableaux
Pour finir, il est tout à fait possible de construire des tableaux de p-uplets ou des tableaux de tableaux. Cette fonctionnalité peut parfois être très pratique.
Création d'un tableau de tableaux
On peut créer un tableau qui contient des tableaux :
>>> t0 = [0, 0, 0]
>>> t1 = [1, 1, 1]
>>> t2 = [2, 2, 2]
>>> t = [t0, t1, t2]
>>> t
[[0, 0, 0], [1, 1, 1], [2, 2, 2]]
Il était possible d'écrire directement :
Il est aussi possible de construire le tableau de tableaux ligne par ligne.
>>> t = []
>>> for i in range(3):
... t_i = [i for j in range (3)]
... t.append(t_i)
...
>>> t
[[0, 0, 0], [1, 1, 1], [2, 2, 2]]
Ou par compréhension.
par exemple, cette compréhension de tableaux combine les éléments de deux tableaux s'ils ne sont pas égaux :
>>> table = [[x, y] for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
>>> table
[[1, 3], [1, 4], [2, 3], [2, 1], [2, 4], [3, 1], [3, 4]]
Exercice corrigé
Construire le tableau de tableaux suivant par compréhension :
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]]
Réponse
ou alorsAccès aux éléments
Pour accéder à un élément du tableau de tableaux, on utilise l'indiçage habituel :
Pour accéder à un élément d'un sous-tableau, on utilise un double indiçage :
Dans le cas d'un tableau de tableaux avec des sous-tableaux de même taille, on parle parfois de matrice.
On dit que cette matrice a 2 dimensions et est de taille 3 x 3. Les éléments sont donc identifiés par t[no de ligne][no de colonne]
.
Exercice corrigé
Ecrire une fonction lucas(a, b, c)
prenant en paramètres 3 entiers relatifs a
, b
et c
, vérifie par asserts que 0 < a < b < c – a
et b ≠ 2a
puis ernvoie le carré magique 3x3 en utilisant la méthode d'Edouard Lucas sous forme d'un tableau de tableaux :
c + a | c – a – b | c + b |
c – a + b | c | c + a – b |
c – b | c + a + b | c – a |
« En mathématiques, un carré magique d'ordre n est composé de \(n^2\) entiers strictement positifs, écrits sous la forme d'un tableau carré. Ces nombres sont disposés de sorte que leurs sommes sur chaque rangée, sur chaque colonne et sur chaque diagonale principale soient égales. » source : https://fr.wikipedia.org/wiki/Carré_magique_(mathématiques)
Réponse
Exercice corrigé
Ecrire une fonction qui vérifie qu'un carré est magique (ou pas). « En mathématiques, un carré magique d'ordre \(n\) est composé de \(n^2\) entiers strictement positifs, écrits sous la forme d'un tableau carré. Ces nombres sont disposés de sorte que leurs sommes sur chaque rangée, sur chaque colonne et sur chaque diagonale principale soient égales. » source : https://fr.wikipedia.org/wiki/Carré_magique_(mathématiques)
Réponse
Tableaux muables
Les tableaux sont muables c'est-à-dire qu'on peut modifier chaque élément d'un tableau individuellement, supprimer ou ajouter des éléments. Mais on peut aussi modifier les variables de type int
, float
, tuple
, str
ou bool
pourtant dit « immuables », alors qu'elle est la différence ?
Observons la différence quand on modifie la valeur d'une variable en utilisant la fonction id()
qui renvoie l'identifiant de la variable en mémoire.
Copie de tableau
Comparons ce qu'il se passe quand on copie une variable immuable, par exemple de type int
, et une variable de type list
muable.
Les deux variables t
et u
ne sont pas deux objets différents mais deux noms qui font référence au même objet en mémoire. Pour s'en convaincre on peut vérifier les adresses des variables
Pour copier un tableau , il faut créer une copie explicite du tableau initial. Cela peut se faire de plusieurs manières6 :
-
Avec
t[:]
qui créé une copie des données du tableaut
(en opposition à une copie du tableaut
) : -
Avec la fonction
list(t)
qui renvoie un tableau formé des éléments de la variablet
: -
Ou encore utiliser la méthode
.copy()
:
Tableau passé en paramètre de fonction
Passer des arguments à une fonction d'un type muable comme list
7 génère des effets de bord8 .
Nous avons vu précédemment qu'une fonction ne modifie pas la valeur d'une variable passée en paramètre en dehors de son exécution, les paramètres sont passés par valeur. C'est en effet le cas avec des variables de type immuable mais ce n'est pas le cas pour les variables de type muable comme le type lis
t. Dans ce cas, la fonction reçoit l'adresse en mémoire de la variable passée en argument et peut donc en modifier le contenu.
Illustrons cela des fonctions f(x)
et g(x)
qui modifient simplement la valeur d'un paramètre x
.
Appelons ces fonctions en passant des variables a
et t
en paramètre 9:
Autres effets
On peut initialiser un tableau avec une valeur par défaut pour tous les éléments, par exemple des zéros, avec
Mais attention à ne pas utiliser cette méthode pour des tableaux de tableaux :
>>> t = [[0] * 3] * 3
>>> t
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> t[0][0] = 1
>>> t
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
On préfèrera donc : t = [0 for i in range(3)]
et t = [[0 for i in range(3)] for i in range(3)]
De la même façon, on ne doit pas définir une valeur par défaut de paramètre de fonction avec un tableau de type list
10, par exemple dans la fonction suivante :
La valeur par défaut n'est évaluée qu'une seule fois puis la fonction accumule les arguments au fil des appels :
Pour finir, il revient au même de faire par exemple n += 1
et n = n + 1
pour des entiers mais par pour des tableaux. Comparons :
def f(L, n) :
for k in range(n) :
L += [k] # equivalent à L.append(), modifie la valeur de l'argument L
def g(L, n) :
for k in range(n) :
L = L + [k] # crée une nouvelle variable 'locale' L et ne modifie par l'argument L
-
ou mutable en anglais. ↩
-
Par abus de langage on francise parfois le terme en « liste » pour désigner un tableau. ↩
-
Le type
list
de Python offre plus de possibilité qu'un tableau et notamment peut contenir des éléments de types différents (y compris d'autres tableaux). ↩ -
Il est aussi possible de préciser un
pas
sur le modèlet[début:fin:pas]
. ↩ -
del
est une instruction Python, pas une fonction, elle s'écrit donc sans parenthèse. ↩ -
Aucune de ces approches ne fonctionne pour un tableau de tableaux, il faut par exemple utiliser la méthode
.deepcopy()
du modulecopy
. ↩ -
Ou de type
dict
ouset
qui sont aussi des types muables. ↩ -
Un effet de bord se produit quand une fonction modifie le contenu d'une variable qui appartient au contexte appelant. ↩
-
Les variables
a
ett
pourraient s'appeler aussix
ce qui donnerait le même résultat. ↩ -
Voir https://docs.python.org/fr/3/tutorial/controlflow.html#default-argument-values. ↩