Formation I.S.N.

Les listes

Création d'une liste

On a jusqu’à présent écrit des programmes utilisant des types int, float ou booléan. Une boîte d’un tel type contient une valeur formée d’un unique nombre (encodé sur un ou plusieurs bits).

Dans de nombreuses situations on a besoin d’utiliser des valeurs qui, comme les chaînes de caractères, les sons ou les images sont formés de plusieurs nombres. Ces valeurs sont dites de type composite.

Les valeurs de type str en sont un premier exemple. Il existe également le type list que nous allons décrire dans ce qui suit. Si l’on veut utiliser une boîte qui contient dix nombres entiers, par exemple les dix premières décimales du nombre π, on utilisera dans le programme une variable t de type list.



Pour ajouter une telle boîte à l’état d’exécution du programme, on utilise une nouvelle construction : l’allocation. La boîte associée à la liste t commence par être vide puis elle se remplit d’autant de valeurs qui lui est allouée par le programme, chaque valeur occupant une nouvelle « sous-boîte ».


				
				

L’instruction t = [] créé une liste vide.

L’instruction t = [0 for i in range(10)] crée 10 « sous-boîtes » de la boîte t toutes associées à la valeur 0.

Boîtes de la liste t

Avec cette notion d’allocation d’une liste apparaissent donc les nouvelles notions de référence d’une boîte. Ainsi ces deux constructions (allocation et référence) permettent l’affectation d’une valeur à une boîte mais aussi l’accès à une boîte.

Pour une liste L de n éléments, l’instruction L[p] = expressionp est une expression dont la valeur est comprise entre 0 et n – 1 permet de remplacer l’élément d’indice p de la liste L par la valeur de expression.



Par exemple si nous voulons remplacer la valeur de l’élément d’indice 3 de la liste t par la valeur 4, nous allons saisir l’instruction suivante :


				
				

Attention : les éléments sont numérotés de 0 à n – 1. Ainsi l’élément numéro 3 est en fait en 4ème position dans la liste.

Comme pour les suites numériques sont le 1er terme est u0, il y a un décalage de 1 entre le rang et l’indice.



On peut aussi saisir d’instruction :


				
				

On affecte à l’élément d’indice 1 (le 2ème) la valeur 6 (3 + 3).



Remarque : une chaîne de caractères intègre également la notion de référence. Ses éléments sont donc atteignables mais pas mutables. Ainsi le script suivant génère une erreur :


			chaine = "bonjour"
			print(chaine[0])	#La lettre "b" s'afficher
			
			chaine[0] = "p"		#Erreur : l'élément n'est pas mutable
			

Exercice 1

  1. Écrire une liste contenant les 20 premiers entiers naturels non nuls.
  2. Écrire une liste contenant les cubes des nombres suivants préalablement inscrits dans la liste L : L = [3, 4, 8, 10, 12, 16].
  • Une piste ?
  • Solution ?
Utiliser une boucle for.

1°/


					entiers = [k for k in range(1,21)]
					print(entiers)
					


2°/


					L = [3, 4, 8, 10, 12, 16]
					print(L)
					cubes = [k**3 for k in L]
					print(cubes)
					

Exercice 2

Construire un répertoire associant cinq numéros de téléphone à cinq noms.

Pour cela, créer deux listes vides de chaînes de caractères et remplir les deux listes en affectant une valeur (chaîne de caractères) à chacun des éléments de la liste.

Créer ensuite un script permettant à un utilisateur de rechercher le numéro de téléphone associé à un nom qu’il aura saisi.

  • Une piste ?
  • Solution ?
Créer deux listes vides nom et tel et les remplir élément par élement.

					nom = ["" for i in range(5)]
					tel = ["" for j in range(5)]
					nom[0] = "Alice"
					tel[0] = "0606060606"
					nom[1] = "Paul"
					tel[1] = "0606060707"
					nom[2] = "Bérangère"
					tel[2] = "0606060809"
					nom[3] = "Arthur"
					tel[3] = "0605060406"
					nom[4] = "Marine"
					tel[4] = "0601106060"

					s = input("Saisir le nom de la personne dont vous recherchez le numéro de téléphone : ")
					k = 0
					while k < 5 and nom[k] != s:
						k += 1
    
					if k < 5:           #Structure conditionnelle permettant de débugger un nom inconnu
						print(tel[k])
					else:
						print("Inconnu")
					

Quelques opérations courantes sur les listes

Insérer des éléments dans une liste

On dispose de plusieurs méthodes définies dans la classe list pour ajouter des éléments dans une liste.

  1. Ajouter un élément à la fin de la liste : méthode append
    
    					
    					

    L’élément 56 se rajoute en dernière position.



  2. Insérer un élément dans la liste : méthode insert.
    
    					
    					

    L’élément ‘c’ se rajoute en position d’indice 2.



  3. Concaténer des listes : méthode extend
    
    					
    					

    liste1 contient maintenant tous les éléments de liste1 et de liste2.

    ou encore

    
    					
    					

    ou encore

    
    					
    					


Supprimer des éléments d'une liste

  1. Avec le mot-clé del

    del (abréviation de delete) signifie « supprimer » en anglais. Il s’agit d’un mot-clé qui peut s’utiliser avec toute sorte d’objet.

    On peut par exemple supprimer le contenu d’une variable : il suffit de saisir del nom_variable.

    Mais on peut également supprimer des éléments d’une séquence, comme une liste :

    
    					
    					

    Le mot-clé del a permis de supprimer l’élément d’indice 3 de liste.

  2. Par la méthode remove
    
    					
    					

    On constate ici que l’on agit pas sur l’indice de l’élément à supprimer mais sur sa valeur. La méthode remove parcourt la liste et en retire l’élément qu’elle a reçu en argument.

    Attention : elle ne retire que la première occurrence rencontrée !!

Le parcours de liste

Le parcours de liste consiste à venir « lire » chaque élément d’une liste pour éventuellement en extraire pour un traitement particulier.

Il existe deux scripts possibles pour parcourir une liste :


					
					

ou bien


					
					

L’inconvénient de ces deux scripts tient dans le fait qu’ils permettent de capturer les éléments d’une liste sans aucune information sur leur position dans la liste.

Pour remédier à ce problème (qui n’en est pas non plus un dans tous les cas), on dispose d’une fonction enumerate. Voici son fonctionnement :


					
					

Quand on parcourt chaque élément par la fonction enumerate, on voit des tuples (voir plus bas pour la définition de ce type) qui contiennent deux éléments : l’indice puis l’objet se trouvant à cet indice.

Des chaînes aux listes

Pour « convertir » une chaîne en liste, on va utiliser une méthode de chaîne nommée split (éclater en anglais). Cette méthode prend un paramètre qui est une autre chaîne, souvent d’un seul caractère, définissant la façon dont on va découper notre chaîne initiale.


					
					

ou encore


					
					

Ainsi, quand on appelle la méthode split, celle-ci découpe la chaîne en fonction du paramètre donné. Le premier élément de la liste va donc du premier caractère de la chaîne au dernier avant le caractère-paramètre ; le deuxième élément de la liste va du caractère suivant au prochain précédent le caractère-paramètre etc.

Il faut savoir que split possède en fait un paramètre par défaut, un code qui représente les espaces, les tabulations et les sauts de ligne. Donc écrire liste.split() aurait donné le même résultat dans notre premier exemple.

Des listes aux chaînes

Voyons l’inverse à présent, c’est-à-dire transformer une liste contenant plusieurs chaînes de caractères en une seule.

On utilise pour cela la méthode de chaîne join (joindre en anglais). Sa syntaxe est la suivante :


					
					

En paramètre de la méthode join, on passe la liste des chaînes que l’on souhaite ressouder. La méthode va travailler sur l’objet qui l’appelle, ici une chaîne de caractères contenant un unique espace.

Copier une liste, attention danger !

Commençons par quelque chose de déroutant et parfois dur à repérer dans de grands codes.


					
					

Regardez bien ce qu'il vient de se passer : les deux listes ont été modifiées!
Si cela ne vous choque pas, comparez avec le code suivant.


					
					

Que s'est il passé avec nos listes, ou peut-être devrait-on dire avec notre liste ?
Une liste est un objet informatique qui consomme beaucoup de mémoires, par conséquent les concepteurs de Python ont choisi de limiter la copie en mémoire des listes.
Dans notre cas, ceci signifie que les variables liste_1 et liste_2 pointent vers le même emplacement mémoire d'une unique liste (ce phénomène se rencontre aussi avec les variables de type ensemble et dictionnaire ).

Nous devons donc nous débrouiller pour imposer la création d'une nouvelle copie en mémoire.
Voici une méthode propre qui fait appel à un module dédié à la copie d'objets "mémophages". Nous proposons d'utiliser deepcopy qui va gérer aussi les cas de listes contenants des listes contenant des listes... etc.