Les listes

Les listes (ou tableaux, ou matrices) sont un élément essentiel de tout langage de programmation.

Il s'agit d'une structure permettant de stocker plusieurs données en même temps. On peut penser à une colonne d'un tableau, mais une colonne dont la taille n'est pas limitée, a priori (sauf bien sûr par la quantité de mémoire disponible).

Création, accès, modification

En Python, une liste est encadré par des crochets [...] et les valeurs de la liste par des virgules.

In [16]:
L = [7, 'a', 4.13, 2, 5, 'z']
In [17]:
L
Out[17]:
[7, 'a', 4.13, 2, 5, 'z']

Notez qu'une liste peut contenir des données de types différents (quoique ces listes hétérogènes soient complexes à utiliser).

Indices

On accède à un élément d'une liste par l'entier qui désigne sa place dans la liste. Attention : ces indices commencent à 0.

In [18]:
L[0]
Out[18]:
7
In [19]:
L[4]
Out[19]:
5

On peut utiliser des indices négatifs. L'indice -1 désigne le dernier élément de la liste, puis, en remotant, on a les éléments d'indices -2, -3, etc.

In [20]:
L[-1]
Out[20]:
'z'
In [21]:
L[-2]
Out[21]:
5

On peut ainsi créer des listes de listes, l'équivalent de tableaux à double entrée.

In [23]:
M = [[1, 2], [3, 4], [7, 'a', 4.13, 2, 5, 'z']]

On accède aux valeurs de M par un système de double indice.

In [24]:
M[1][0]
Out[24]:
3

Modification

Pour modifier un des éléments de la liste, il suffit d'une simple affectation, en utilisant son indice.

In [25]:
L[2] = 2
In [26]:
L
Out[26]:
[7, 'a', 2, 2, 5, 'z']
In [27]:
L[1] = 4
In [28]:
L
Out[28]:
[7, 4, 2, 2, 5, 'z']
In [29]:
L[1] = L[0] + 3
In [30]:
L
Out[30]:
[7, 10, 2, 2, 5, 'z']
In [31]:
L[-1] = 12.5
In [32]:
L
Out[32]:
[7, 10, 2, 2, 5, 12.5]

Sous-listes

Il est possible d'extraire une sous-liste d'une liste, avec la syntaxe : L[ : ] ce qui a pour effet de sélectionner la liste entre les indices <index de début> et <index de fin>-1. Attention au -1 !

In [33]:
L[2:4]
Out[33]:
[2, 2]
In [34]:
L[1:-1]
Out[34]:
[10, 2, 2, 5]

On peut omettre 0 lorsqu'on veut commencer au début de la liste.

In [35]:
L[0:4]
Out[35]:
[7, 10, 2, 2]
In [36]:
L[:4]
Out[36]:
[7, 10, 2, 2]

Enfin, pour aller jusqu'à la fin de la liste :

In [37]:
L[:]
Out[37]:
[7, 10, 2, 2, 5, 12.5]

Opérations sur les listes

Plusieurs opérations sont possibles. L'addition entre listes permet de concaténer deux listes.

In [38]:
A = [1, 2, 4]
B = [2, 3, 5]
A = A + B
In [39]:
A
Out[39]:
[1, 2, 4, 2, 3, 5]

La multiplication permet de répéter une liste plusieurs fois.

In [40]:
[0,1]*5
Out[40]:
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

La fonction len() renvoie la longueur d'une liste.

In [41]:
len(A)
Out[41]:
6

Enfin il existe un test possible avec les liste : x in A renvoie True si l'élément x est dans la liste A et False sinon.

In [42]:
A
Out[42]:
[1, 2, 4, 2, 3, 5]
In [43]:
7 in A
Out[43]:
False
In [44]:
2 in A
Out[44]:
True

Exercices

Proposer une méthode pour agrandir la liste A en lui ajoutant un terme à la fin, puis au début, et enfin au milieu.

In [45]:
A = A + [10000]
In [46]:
A
Out[46]:
[1, 2, 4, 2, 3, 5, 10000]
In [47]:
A = [10000] + A
A
Out[47]:
[10000, 1, 2, 4, 2, 3, 5, 10000]
In [48]:
A = A[0: len(A)//2] + [10000] + A[len(A)//2:len(A)]
In [49]:
A
Out[49]:
[10000, 1, 2, 4, 10000, 2, 3, 5, 10000]

Listes et boucles

Les listes s'entendent particulièrement bien avec les boucles for. Grâce à une boucle sur les indices de la liste, on peut travailler sur cette liste.

Voici par exemple un moyen d'afficher tous les éléments strictement positifs d'une liste.

In [50]:
L = [1, 0, -1 , 5, 12, -4, 13.2]
M = []
for i in range(len(L)):
    if L[i] >0:
        M.append(L[i])
        

Remarquez que i désigne l'indice d'un élément, et pas cet élément lui-même : i est l'indice et L[i] est l'élément.

Les boucles sont particulièrement utiles pour créer des listes. Créons par exemple la liste des 5 premières puissances de 2.

In [51]:
L = []
for i in range(5):
    L = L + [2**i]
L
Out[51]:
[1, 2, 4, 8, 16]
In [52]:
L
Out[52]:
[1, 2, 4, 8, 16]

Exercice Proposer une fonction somme_liste(A,B) qui prend en paramètres deux listes de mêmes longueurs et qui renvoie la liste constituée de la somme des éléments de A et B.

In [53]:
def somme_liste(A, B):
    C = []
    for i in range(0,len(A)):
        C.append(A[i] + B[i])
    return C

somme_liste([0,1,2], [0,1,2]) 
Out[53]:
[0, 2, 4]

Exercice Proposer une fonction majore_par(L, m) qui prend une liste L et une valeur m en paramètre et qui renvoie True si tous les éléments de la liste sont inférieurs à m et False sinon.

In [54]:
def majore_par(L,m):
    V = True
    for i in range(0, len(L)):
        if L[i] >= m:
            V = False
    return V
            
def majore_par2(L,m):
    for i in range(0, len(L)):
        if L[i] >= m:
            return False
    return True

majore_par2([1,3,5,6,3], 10)
majore_par2([1,3,5,6,3], 4)
Out[54]:
False

Ce n'est pas Clark Kent, c'est Superman !

Il est tant de vous faire une révélation : les types de variables que nous avons rencontré jusqu'ici sont beaucoup plus puissants que ce que je vous ai dit.

Prenons l'exemple d'une chaîne de caractères :

In [55]:
s = 'abc'

Il est possible de mettre cette chaîne de caractère en majuscules, à l'aide de upper()

In [56]:
s.upper()
Out[56]:
'ABC'

Mais qu'a-t-on fait ? Au lieu d'appeler la fonction upper() avec l'argument s (upper(s)) on a demandé à la variable s d'éxecuter sa méthode upper(), qui a renvoyé s en majuscules.

En fait s est plus qu'une variable : c'est un objet. Un objet est une variable d'un type très évolué : non seulement elle contient une valeur (ici "abc") mais de plus elle a des super-pouvoirs ! Elle est livré avec des fonctions spécifiques qui augmentent ses capacités.

Ces fonctions s'appellent dees méthodes. Python implémente automatiquement un bon nombre de méthodes pour les objets courants, et il est possible de les modifier, d'en ajouter, etc.

On parle de \voc{programmation orienté objet}, en abrégé POO. Un langage non orienté objet est aussi puissant (entendre « fait les mêmes choses que ») qu'un langage orienté objet. Par exemple les deux types de commandes suivantes, qui font la même chose, coexistaient dans des versions antérieures de Python.

upper(s)
s.upper()

La programmation orientée objet est un « paradigme » de programmation, c'est-à-dire une façon de programmer que l'on peut adopter ou non. Elle s'est avéré bien adaptée à l'échange et à la diffusion des librairies logicielles, ce qui fait que ce paradigme est l'un des plus répandu aujourd'hui.

Les méthodes de listes

Dans le cas des listes, il existe plusieurs méthodes très commodes. Voici les principales :

`L.insert(i, x)`
Insère dans la liste `L` l'élément `x` à l'indice `i`.
In [57]:
L = [0, 1, 2, 3]
L.insert(2, 14)
In [58]:
L
Out[58]:
[0, 1, 14, 2, 3]
In [59]:
L.insert(len(L)//2, 10000)
L
Out[59]:
[0, 1, 10000, 14, 2, 3]
`L.append(x)`
Ajoute l'élément `x` à la fin de la liste `L`.
In [60]:
L = [1, 2, 4, 8, 16]
L
Out[60]:
[1, 2, 4, 8, 16]
In [61]:
L.append(34)
L
Out[61]:
[1, 2, 4, 8, 16, 34]
In [62]:
L = L+[34]
In [63]:
L
Out[63]:
[1, 2, 4, 8, 16, 34, 34]

On dispose donc de deux façons d'ajouter un élément à la fin d'une liste : L.append(x) et L = L + [x]. Laquelle est la meilleure ?

append ! Et de loin ! En effet, la méthode append se contente vraiment d'ajouter un élément à la fin de la liste. De façon imagée, elle va chercher en mémoire la liste L, se placer à la fin et ajouter un élément.

Au contraire L = L + [x] est plus complexe. On va d'abord évaluer le terme de droite, ce qui implique de recopier quelque part en mémoire la liste L. Puis à cette copie on ajoute l'élément x (en utilisant le append de cette copie...) puis on donne à cette copie le nom L. Il faut imaginer qu'on manipule couramment des listes de plusieurs milliers ou plusieurs millions d'items (des images, des sons, des bases de données, etc.). Du coup cette étape de recopie est très chronophage... et parfaitement inutile !

`L.extend(A)`
Ajoute à la fin de la liste `L` les éléments de la liste `A`.
In [64]:
A = [1,2,3,4]
B = [5, 2, 10]
In [65]:
A.extend(B)
In [66]:
A
Out[66]:
[1, 2, 3, 4, 5, 2, 10]

Est donc équivalente à A = A + B, mais en beaucoup mieux !

`L.remove(x)`
Supprime la première occurence de l'élément `x` dans la liste `L`.
In [67]:
A = [2,4,2,5,2,7]
A.remove(2)
A
Out[67]:
[4, 2, 5, 2, 7]
`L.pop(i)`
Supprime et renvoie l'élément d'indice `i` de la liste `L`.
In [68]:
A.pop()
Out[68]:
7
In [69]:
A
Out[69]:
[4, 2, 5, 2]

Exercices

  1. Écrire une fonction positifs_liste(L) qui prend en paramètre une liste L et qui renvoie la liste des éléments de L qui sont positifs.

  2. Écrire une fonction min(L)qui renvoie le minimum de la liste L.

  3. Écrire un fonction testtri(L)qui renvoie Truesi la liste L est triée dans l'ordre croissant et False sinon.

  4. Écrire une fonction minmax(L) qui prend en paramètre une liste L qui renvoie la liste construite ainsi : en début de liste il y a tous les éléments de L plus petits que L[0], puis l'élément L[0] et en fin de liste tous les éléments plus grands que L[0].

In [70]:
def min(L):
    m = L[0]
    for i in range(len(L)):
        if L[i] < m:
            m = L[i]
    return m
In [71]:
def min(L):
    i = 0
    while L[i+1]>L[i] and i<len(L)-2:
        i = i + 1
    if i == len(L)-2:
        return True
    else:
        return False
In [72]:
min([4,3,2,1,-10,6])
Out[72]:
False
In [73]:
def listetriee(L):
    for i in range(len(L)-1):
        if L[i] > L[i+1]:
            return False
    return True
    
    
    
In [74]:
listetriee([1])
Out[74]:
True
In [75]:
def minmax(L):
    A = []
    B = []
    for i in range(1, len(L)):
        if L[i]<L[0]:
            A.append(L[i])
        else:
            B.append(L[i])
    return (A + [L[0]] + B)

minmax([0,-1,1,-2,2])
def minmax(L):
    A = []
    C = 0
    for i in range(1, len(L)):
        if L[i]<L[0]:
            A.insert(0,L[i])
            C = C + 1
        else:
            A.append(L[i])
    A.insert(C, L[0])
    return (A)

minmax([0,-1,1,-2,2])

def minmax(L):
    A = [L[0]]
    for i in range(1, len(L)):
        if L[i]<L[0]:
            A.insert(0,L[i])
        else:
            A.append(L[i])
    return (A)
minmax([0,-1,1,-2,2])
Out[75]:
[-2, -1, 0, 1, 2]