Les listes et tuples (1/2)

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Créons et éditons nos premières listes

D'abord c'est quoi, une liste ?


En Python, les listes sont des objets qui peuvent en contenir d'autres. C'est donc un ensemble, comme une chaîne de caractères, mais qui, au lieu de contenir des caractères, contient n'importe quel objet. Comme d'habitude, on va s'occuper du concept des listes avant de voir tout son intérêt
smile.png
.

Création de listes


On a deux moyens de créer des listes. Si je vous dis que la classe d'une liste s'appelle, assez logiquement, list, vous devriez déjà pouvoir trouver une manière de créer une liste.

Non ? ...
smile.png


Vous allez vous habituer à cette syntaxe :

Code : Python Console1
2
3
4
5
6
>>> ma_liste = list() # on créée une liste vide
>>> type(ma_liste)
<class 'list'>
>>> ma_liste
[]
>>>




Là encore, on appelle la classe comme une fonction pour instancier un objet de cette classe.

Quand vous affichez la liste, vous pouvez constater qu'elle est vide. Entre les crochets (qui sont les délimiteurs des listes en Python), il n'y a rien. On peut également utiliser ces crochets pour créer une liste.

Code : Python Console1
2
>>> ma_liste = [] # on créée une liste vide
>>>




Ça revient au même, vous pouvez vérifier. Toutefois, on peut également créer une liste non vide, en lui indiquant les objets à y mettre directement à la création.

Code : Python Console1
2
3
4
>>> ma_liste = [1, 2, 3, 4, 5] # une liste avec cinq objets
>>> print(ma_liste)
[1, 2, 3, 4, 5]
>>>




La liste que nous venons de créer compte cinq objets du type int. Ils sont classés par ordre croissant. Mais rien de tout cela n'est obligatoire.


  • Vous pouvez faire des listes de toute longueur.
  • Les listes peuvent contenir n'importe quel type d'objet.
  • Les objets dans une liste peuvent être mis dans le désordre. Toutefois, la structure d'une liste fait que chaque objet a sa place et que l'ordre compte.


Code : Python Console1
2
>>> ma_liste = [1, 3.5, "une chaine", []]
>>>




Nous avons ici créer une liste contenant quatre objets de types différents : un entier, un flottant, une chaîne de caractères et... une autre liste
clin.png
.

Voyons à présent comment accéder aux éléments d'une liste :

Code : Python Console1
2
3
4
5
6
7
8
9
>>> ma_liste = ['c', 'f', 'm']
>>> ma_liste[0] # on veut accéder au premier élément de la liste
'c'
>>> ma_liste[2] # troisième élément
'm'
>>> ma_liste[1] = 'Z' # on remplace 'f' par 'Z'
>>> ma_liste
['c', 'Z', 'm']
>>>




Comme vous pouvez le voir, on accède aux éléments d'une liste de la même façon qu'on accède aux caractères d'une chaîne de caractères : on indique entre crochets l'indice de l'élément qui nous intéresse. Rappelez-vous que l'on commence à compter à partir de 0.

Contrairement à la classe str, la classe list vous permet de remplacer un élément par un autre. Les listes sont en effet des types dits mutables.

Ajouter des objets dans une liste


On peut trouver plusieurs méthodes, définies dans la classe list, pour ajouter des éléments dans une liste.

Ajouter un élément à la fin de la liste


On utilise la méthode append pour ajouter un élément à la fin de la liste.

Code : Python Console1
2
3
4
5
>>> ma_liste = [1, 2, 3]
>>> ma_liste.append(56) # on ajoute 56 à la fin de la liste
>>> ma_liste
[1, 2, 3, 56]
>>>




Comment ça, je sais pas compter ?
hihi.png


C'est assez simple non ? On passe en paramètre de la méthode append l'objet que nous souhaitons ajouter à la fin de la liste.

Attention ! La méthode append, comme beaucoup de méthodes de listes, travaille directement sur l'objet et ne retourne rien.


Ceci est extrêmement important. Dans le chapitre précédent, nous avons vu que toutes les méthodes de chaînes ne modifient pas l'objet d'origine mais retournent l'objet modifié. Ici c'est le contraire : les méthodes de listes ne retournent rien mais modifient l'objet d'origine. Regardez ce code si ce n'est pas bien clair :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> chaine1 = "une petite phrase"
>>> chaine2 = chaine1.upper() # on met en majuscule chaine1
>>> chaine1 # on affiche la chaîne d'origine
'une petite phrase'
>>> # elle n'a pas été modifiée par la méthode upper
... chaine2 # on affiche chaine2
'UNE PETITE PHRASE'
>>> # c'est chaine2 qui contient la chaîne en majuscule
... # voyons pour les listes à présent
... liste1 = [1, 5.5, 18]
>>> liste2 = liste1.append(-15) # on ajoute -15 à liste1
>>> liste1 # on affiche liste1
[1, 5.5, 18, -15]
>>> # cette fois, l'appel de la méthode a modifié l'objet d'origine (liste1)
... # voyons ce que contient liste2
... liste2
>>> # rien ? Vérifions avec print
... print(liste2)
None
>>>




Je vais expliquer les dernières lignes. Mais d'abord, il faut que vous fassiez bien la différence entre les méthodes de chaînes, où l'objet d'origine n'est jamais modifié mais qui retournent un nouvel objet, et les méthodes de listes, qui ne retournent rien mais modifient l'objet d'origine.

J'ai dit que les méthodes de listes ne retournent rien. On va pourtant essayer de capturer la valeur de retour dans liste2. Quand on essaye d'afficher la valeur de liste2 en l'entrant directement, on n'obtient rien. Il faut l'afficher avec print pour savoir ce qu'elle contient : None. C'est l'objet vide de Python. En réalité, quand une fonction ne retourne rien, elle retourne None. Vous retrouverez peut-être ce mot-clé de temps à autre, ne soyez donc pas surpris.

Insérer un élément dans la liste


Nous allons passer assez rapidement sur cette seconde méthode. On peut, très simplement, insérer un objet dans une liste, à l'endroit voulu. On utilise pour cela la méthode insert.

Code : Python Console1
2
3
4
>>> ma_liste = ['a', 'b', 'd', 'e']
>>> ma_liste.insert(2, 'c') # on insère 'c' à l'indice 2
>>> print(ma_liste)
['a', 'b', 'c', 'd', 'e']




Quand on demande d'insérer 'c' à l'indice 2, la méthode va décaler les objets d'indice supérieur ou égal à 2. 'c' va donc s'intercaler entre 'b' et 'd'.

Concaténation de listes


On peut également agrandir des listes en les concaténant avec une autre :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
>>> ma_liste1 = [3, 4, 5]
>>> ma_liste2 = [8, 9, 10]
>>> ma_liste1.extend(ma_liste2) # on insère ma_liste2 à la fin de ma_liste1
>>> print(ma_liste1)
[3, 4, 5, 8, 9, 10]
>>> ma_liste1 = [3, 4, 5]
>>> ma_liste1 + ma_liste2
[3, 4, 5, 8, 9, 10]
>>> ma_liste1 += ma_liste2 # identique à extend
>>> print(ma_liste1)
[3, 4, 5, 8, 9, 10]
>>>




Voici les différentes façons de concaténer des listes. Vous pouvez remarquer l'opérateur + qui concatène deux listes entre elles et retourne le résultat. On peut utiliser += assez logiquement pour étendre une liste. Cette façon de faire revient au même qu'utiliser la méthode extend.

Suppression d'éléments d'une liste


Nous allons voir rapidement comment supprimer des éléments d'une liste avant d'apprendre à les parcourir. Vous allez vite pouvoir constater que ça se fait assez simplement. Nous allons voir deux méthodes pour supprimer des éléments d'une liste :


  • Le mot-clé del
  • La méthode remove


Le mot-clé del


C'est un des mot-clés de Python, que j'aurais pu vous montrer plus tôt. Mais les applications de del me semblaient assez peu pratiques avant d'aborder les listes.

del (abréviation de delete) signifie "supprimer" en anglais. Son utilisation est des plus simple : del variable_a_supprimer . Voyons un exemple :

Code : Python Console1
2
3
4
5
6
7
8
9
>>> variable = 34
>>> variable
34
>>> del variable
>>> variable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'variable' is not defined
>>>




Comme vous le voyez, après l'utilisation de del, la variable n'existe plus. Python l'efface tout simplement. Mais on peut également utiliser del pour supprimer des éléments d'un ensemble, comme une liste, et c'est ce qui nous intéresse ici.

Code : Python Console1
2
3
4
5
6
7
8
>>> ma_liste = [-5, -2, 1, 4, 7, 10]
>>> del ma_liste[0] # on supprime le premier élément de la liste
>>> ma_liste
[-2, 1, 4, 7, 10]
>>> del ma_liste[2] # on supprime le troisième élément de la liste
>>> ma_liste
[-2, 1, 7, 10]
>>>




Si vous entrez del ma_liste[0] , le premier élément de la liste sera supprimé de ma_liste. Simple non ?

La méthode remove


On peut aussi supprimer des éléments de la liste grâce à la méthode remove qui prend en paramètre, non pas l'indice de l'élément à supprimer, mais l'élément lui-même.

Code : Python Console1
2
3
4
5
>>> ma_liste = [31, 32, 33, 34, 35]
>>> ma_liste.remove(32)
>>> ma_liste
[31, 33, 34, 35]
>>>




La méthode remove parcourt la liste et en retire l'élément que vous lui passez en paramètre. C'est une façon de faire un peu différente et vous appliquerez del et remove dans des situations différentes.

Attention ! La méthode remove ne retire que la première occurrence de la valeur trouvée dans la liste.


Notez au passage que le mot-clé del n'est pas une méthode de liste. Il aurait pu l'être. Mais il s'agit d'une fonctionnalité de Python qu'on retrouve dans la plupart des objets conteneurs, tels que les listes que nous venons de voir, ou les dictionnaires que nous verrons plus tard. D'ailleurs, del sert plus généralement à supprimer, pas forcément des éléments d'un ensemble mais aussi, comme nous l'avons vu, des variables.

Nous allons à présent voir comment parcourir une liste, même si vous devez déjà avoir votre petite idée sur la question
clin.png
.
Le parcours de listes

Vous avez déjà dû vous faire une idée des méthodes pour parcourir une liste. Je vais passer brièvement dessus, vous ne verrez rien de nouveau ni, je l'espère, de très surprenant :

Code : Python Console 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
>>> ma_liste = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> i = 0 # notre indice pour la boucle while
>>> while i<len(ma_liste):
... print(ma_liste)
... i += 1 # on incrémente i, ne pas oublier !
...
a
b
c
d
e
f
g
h
>>> for elt in ma_liste: # elt va prendre les valeurs successives des éléments de ma_liste
... print(elt)
...
a
b
c
d
e
f
g
h
>>>




Il s'agit des mêmes méthodes de parcours que nous avons vues pour les chaînes de caractères, dans le chapitre précédent. Nous allons cependant aller un peu plus loin.

La fonction range


Les deux méthodes que nous venons de voir possèdent toutes deux des inconvénients :


  • La méthode par while est plus longue à écrire, moins intuitive et elle est perméable aux boucles infinies, si l'on oublie d'incrémenter la variable servant de compteur
  • La méthode par for se contente de parcourir la liste en capturant les éléments dans une variable ; sans qu'on puisse savoir où ils sont dans la liste.


C'est vrai dans le cas que nous venons de voir. Certains codeurs vont combiner les deux méthodes pour plus de flexibilité, mais très souvent le code obtenu est moins lisible. Heureusement, les développeurs de Python ont pensé à nous.

La fonction range prend au minimum un paramètre, un nombre. Elle retourne une liste contenant tous les entiers de 0 au nombre passé en paramètre moins un.

Code : Python Console1
2
3
>>> range(5)
[0, 1, 2, 3, 4]
>>>>




On utilise parfois cette fonction pour parcourir une liste par la méthode for, mais en utilisant les indices.

Code : Python1
2
for i in range(len(ma_liste)):
print(ma_liste)




Décortiquez un peu cet exemple : on appelle la méthode range et on lui passe en paramètre la taille de ma_liste. La fonction range va donc retourner une liste allant de 0 à la taille de la liste moins un. La liste obtenue est donc la liste des indices de ma_liste. La boucle for travaille sur cette liste d'indice et elle va placer successivement chaque indice dans la variable i.

Pourquoi s'embêter à utiliser range ? On arrivait très bien à parcourir une liste avec for elt in ma_liste .


En effet. Mais dans certaines situations, que nous allons justement voir un peu plus bas, il est plus utile d'avoir les indices d'une liste que les éléments qu'elle contient. Souvenez-vous que grâce aux indices, on peut accéder aux éléments mais que l'inverse n'est pas vrai.

La fonction enumerate


Utiliser la fonction range pour parcourir une liste n'est ni très intuitif ni très élégant. Voici une autre façon de faire que je vais détailler plus bas :

Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
>>> ma_liste = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i,elt in enumerate(ma_liste):
... print("A l'indice {0} se trouve {1}.".format(i, elt))
...
A l'indice 0 se trouve a.
A l'indice 1 se trouve b.
A l'indice 2 se trouve c.
A l'indice 3 se trouve d.
A l'indice 4 se trouve e.
A l'indice 5 se trouve f.
A l'indice 6 se trouve g.
A l'indice 7 se trouve h.
>>>




Pas de panique !
heureux.png


Nous avons ici une boucle for un peu surprenante. Entre for et in, nous avons deux variables, séparées par une virgule.

Regardons d'abord ce que renvoie la fonction enumerate :

Code : Python Console1
2
3
>>> enumerate(ma_liste)
((0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'))
>>>




Ça ne vous aide peut-être pas beaucoup. En fait, enumerate prend une liste en paramètre et retourne un tuple, contenant lui-même d'autres tuples, associant un indice à l'élément correspondant. Nous verrons les tuples un peu plus loin, pour l'instant sachez qu'il s'agit simplement de listes que l'on ne peut pas modifier.

Ce n'est sans doute pas encore très clair. Essayons d'afficher ça un peu mieux :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
>>> for elt in enumerate(ma_liste):
... print(elt)
...
(0, 'a')
(1, 'b')
(2, 'c')
(3, 'd')
(4, 'e')
(5, 'f')
(6, 'g')
(7, 'h')
>>>




Quand on parcourt chaque élément de notre tuple retourné par enumerate, on voit d'autres tuples qui contiennent deux éléments : d'abord l'indice, puis ensuite l'objet se trouvant à cet indice, dans la liste passée en paramètre de la fonction enumerate.

Si les parenthèses vous déconcertent trop, vous pouvez imaginer à la place des crochets, cela revient au même dans cet exemple.

Quand on utilise enumerate, on capture l'indice et l'élément dans deux variables distinctes. Voyons un autre exemple pour comprendre ce mécanisme :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> autre_liste = [
... [1, 'a'],
... [4, 'd'],
... [7, 'g'],
... [26, 'z'],
... ] # on a étalé la liste sur plusieurs lignes
>>> for nb,lettre in autre_liste:
... print("La lettre {0} est la {1}e de l'alphabet.".format(lettre, nb))
...
La lettre a est la 1e de l'alphabet.
La lettre d est la 4e de l'alphabet.
La lettre g est la 7e de l'alphabet.
La lettre z est la 26e de l'alphabet.
>>>




J'espère que c'est assez clair dans votre esprit. Dans le cas contraire, décomposez ces exemples, le déclic devrait se faire.

N.B. : On écrit ici la définition de la liste sur plusieurs lignes pour des raisons de lisibilité. On n'est pas obligé de mettre des anti-slashs \ en fin de ligne car, tant que Python ne trouve pas de crochet fermant la liste, il continue d'attendre sans interpréter la ligne. Vous pouvez d'ailleurs le constater avec les points qui remplacent les chevrons au début de la ligne, tant que la liste n'a pas été refermée.

Quand on travaille sur une liste que l'on parcours en même temps, on peut se retrouver face à des erreurs assez étranges, qui paraissent souvent incompréhensibles au début.


Par exemple, des exceptions IndexError si on tente de supprimer certains éléments d'une liste en la parcourant.

Nous verrons dans le chapitre suivant comment faire cela proprement, pour l'heure qu'il vous suffise de vous méfier d'un parcours qui modifie une liste, sa structure surtout. D'une façon générale, évitez de parcourir une liste dont la taille évolue en même temps.

Allez ! On va jeter un coup d'oeil aux tuples, pour conclure ce chapitre
smile.png
.
Un petit coup d'œil aux tuples

Nous avons brièvement vu les tuples un peu plus haut, grâce à la fonction enumerate. J'avais dit alors que les tuples étaient des listes immutables, que l'on ne pouvait modifier. En fait, vous allez vous rendre compte que nous utilisons depuis longtemps des tuples sans nous en rendre compte.

Un tuple se définit comme une liste, sauf qu'on utilise comme délimiteur des parenthèses au lieu des crochets :

Code : Python1
2
3
tuple_vide = ()
tuple_non_vide = (1,)
tuple_non_vide = (1, 3, 5)




Une petite subtilité ici : si on veut créer un tuple avec un unique élément, on doit quand même mettre une virgule après. Sinon, Python va automatiquement supprimer les parenthèses et on se retrouvera avec une variable lambda et non un tuple contenant cette variable.

Mais à quoi ça sert ?


Il est assez rare que l'on travaille directement sur des tuples. Ce sont après tout des types que l'on ne peut modifier. On ne peut supprimer d'éléments d'un tuple, ni en ajouter. Cela vous paraît peut-être encore assez abstrait, mais il peut être utile de travailler sur des données sans pouvoir les modifier.

Passons en attendant. Voyons plutôt les cas où nous avons utilisé des tuples sans le savoir.

Affectation multiple


Tous les cas que nous allons voir sont des cas d'affectation multiple. Vous vous souvenez ?

Code : Python Console1
2
3
4
5
6
>>> a,b = 3,4
>>> a
3
>>> b
4
>>>




On a également utilisé cette syntaxe pour permuter deux variables. Et bien, cette syntaxe passe par des tuples qui ne sont pas déclarés explicitement. Vous pourriez écrire :

Code : Python Console1
2
>>> (a,b) = (3,4)
>>>




Quand Python trouve plusieurs variables ou valeurs séparées par des virgules et sans délimiteur, il va les mettre dans des tuples. Dans le premier exemple, les parenthèses sont sous-entendues et Python comprend ce qu'il doit faire.

Une fonction retournant plusieurs valeurs


Nous ne l'avons pas vu jusqu'ici, mais une fonction peut retourner deux valeurs, ou même plus :

Code : Python1
2
3
4
5
6
7
def decomposer(entier, divise_par):
"""Cette fonction retourne la partie entière et le reste de
entier / divise_par .
"""
p_e = entier // divise_par
reste = entier % divise_par
return p_e, reste




Et on peut ensuite capturer la partie entière et le reste dans deux variables, au retour de la fonction :

Code : Python Console1
2
3
4
5
6
>>> partie_entiere, reste = decomposer(20, 3)
>>> partie_entiere
6
>>> reste
2
>>>




Là encore, on passe par des tuples sans que ce soit indiqué explicitement à Python. Si vous essayez de faire retour = decomposer(20, 3) , vous allez capturer un tuple contenant deux éléments : la partie entière et le reste de 20 divisé par 3.

Nous verrons plus loin d'autres exemples de tuples, et d'autres utilisations. Je pense que ça suffit pour cette fois. En attendant, direction le QCM !


Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!