IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Programmation Python pour les scientifiques

Listes et autres structures de données - Cours avec exercices corrigés


précédentsommairesuivant

II. Approfondissement sur les listes

II-A. Les méthodes de la classe list

Voir More on Lists.

Méthode

Action

liste.append(x)

Pour ajouter x à la fin de la liste liste.

liste.extend(liste2)

Pour ajouter la liste liste2 à la suite de la liste liste.

liste.insert(i,x)

Pour insérer l'élément x en position i dans liste.

liste.pop()

Pour retirer et renvoyer le dernier élément dans liste.

liste.pop(i)

Pour retirer et renvoyer l'élément en position i dans liste.

liste.remove(x)

Pour retirer la première occurrence de x dans liste.

liste.index(x)

Renvoie la 1re position de x dans liste. Message d'erreur si aucune.

liste.count(x)

Renvoie le nombre d'occurrences de x dans liste.

liste.sort()

Trie la liste par ordre croissant.

liste.reverse()

Renverse l'ordre des éléments de la liste.

II-B. Saucissonnage ou slicing

 
Sélectionnez
>>> liste = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
 
Sélectionnez
>>> liste1 = liste[2:5] # tranche (slice) de la liste
>>> print liste1
['c', 'd', 'e']

L'instruction liste1 = liste[2:5] crée une nouvelle liste liste1 dont les éléments sont ceux de liste allant de l'indice 2 (inclus : le 3e élément) à l'indice 5 (exclu : jusqu'au 5e élément, celui d'indice 4). On l'appelle une tranche (slice en anglais) de la liste.

Les indices entre crochets peuvent sortir de la plage d'indices de la liste :

 
Sélectionnez
>>> liste2 = liste[0:100] # tranche des indices de 0 à 100 
>>> print liste2
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

Un troisième paramètre définit un pas :

 
Sélectionnez
>>> liste3 = liste[6:2:-1] # tranche des indices de 6 à 2 par pas de -1
>>> print liste3
['g', 'f', 'e', 'd']

Les ':' séparent les champs qui sont optionnels.

LISTE[indice départ (inclus) : indice arrivée (exclu) : pas]

Python crée la tranche en copiant l'élément de LISTE d'indice indice de départ, puis tous les éléments obtenus en ajoutant successivement pas à l'indice, tant qu'on ne dépasse pas indice d'arrivée. Par défaut : pas = 1.

  • Si pas>0 : indice départ = 0 ; indice arrivée = len(LISTE)
  • Si pas<0 : indice départ = len(LISTE)-1 ; indice arrivée = -1
 
Sélectionnez
>>> liste4 = liste[::2]    # slicing par pas de 2
>>> print liste4
['a', 'c', 'e', 'g', 'i']
>>> liste5 = liste[::-1]   # slicing par pas de -1
['i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
 
Sélectionnez
>>> liste5 = liste[3::2] # départ de l'indice 3, par pas de 2
>>> print liste5
['d', 'f', 'h']
>>> liste6 = liste[:3:-1]    # départ de la fin par pas de -1, arrêt avant l'indice 3
>>> print liste6
['i', 'h', 'g', 'f', 'e']
 
Sélectionnez
>>> liste7 = liste[:] # Pour copier une liste
>>> print liste7
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

II-C. Copie de liste

Il faut prendre garde à la façon dont Python copie une liste. Illustrons cela sur un exemple.

  • Copie d'une liste : jusqu'ici tout va bien.

     
    Sélectionnez
    >>> liste = ['a', 'b', 'c'] # définition d'une liste
    >>> copie = liste           # puis copie de la liste
    >>> print copie
    ['a', 'b', 'c']
  • Modification d'un élément de la liste originelle. Tout se passe comme prévu.

     
    Sélectionnez
    >>> liste[0] = 'modifié'    # Modifions un élément dans liste
    >>> print liste
    ['modifié', 'b', 'c']
  • Mais, ô surprise, la copie aussi a été modifiée… contrairement à ce qu'on aurait pu attendre.
 
Sélectionnez
>>> print copie             # regardons ce qu'est devenue la copie
['modifié', 'b', 'c']

Explication : en fait, une liste en Python ne contient que l'adresse mémoire où sont stockés ses éléments ; c'est ce que l'on appelle un pointeur.

Image non disponible

Quand on copie liste dans copie, c'est cette adresse mémoire qui est copiée. C'est un alias qui est créé.

Image non disponible

Quand on modifie un élément d'une liste, il est alors aussi modifié dans la copie. L'avantage étant qu'on encombre moins la mémoire centrale puisque les éléments de la liste ne figurent qu'en un seul emplacement mémoire.

Pour preuve, on peut utiliser la fonction intégrée id() qui retourne un entier long étant l'image de l'adresse mémoire où est stocké l'objet passé en argument. Les deux objets ont le même « identifiant ».

 
Sélectionnez
>>> print id(liste), id(copie)
139807842040576 139807842040576

On peut contourner ce problème grâce à copie = liste[:] qui fait une « copie superficielle » :

 
Sélectionnez
>>> liste = ['a', 'b', 'c'] # définition d'une liste
>>> copie = liste[:]        # puis copie superficielle de la liste
>>> print copie
['a', 'b', 'c']
>>> liste[0] = 'modifié'    # Modifions un élément dans liste
>>> print liste
['modifié', 'b', 'c']
>>> print copie             # regardons ce qu'est devenue la copie
['a', 'b', 'c']

Python fait une copie des éléments de la liste, mais c'est l'adresse mémoire des objets qui est copiée. Aussi, si l'un des éléments de la liste est aussi une liste, on retombe sur le même problème :

 
Sélectionnez
>>> liste = ['a', 'b', [0, 1]]  # définition d'une liste
>>> copie = liste[:]            # puis copie superficielle de la liste
>>> liste[0] = 'modifié'        # Modifions un élément dans liste
>>> liste[2][0] = 'MODIF'       # et un élément dans liste[2]
>>> print liste; print copie    # regardons ce qu'est devenue la copie
['modifié', 'b', ['MODIF',1]]
['a', 'b', ['MODIF',1]]

Pour contourner totalement le problème, utilisez la méthode liste.deepcopy() du module standard copy qui effectue une « copie profonde »:

 
Sélectionnez
>>> from copy import deepcopy
>>> copie = deepcopy(liste)

II-D. Listes définies par compréhension

On peut définir une liste à l'aide des mots-clés for, in et if comme on définit un ensemble en mathématiques « en compréhension » :

[f(x) for x in liste] correspond à kitxmlcodeinlinelatexdvp\{ f(x) | x \in liste \}finkitxmlcodeinlinelatexdvp.

Exemple :

 
Sélectionnez
>>> liste = range(10)             # définition de la liste des entiers de 0 à 9
>>> liste_carres = [x**2 for x in liste] # liste des carrés des éléments de liste
>>> print liste_carres
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

[f(x) for x in liste if Condition(x)] correspond à kitxmlcodeinlinelatexdvp\{ f(x) | x \in liste\, \mathrm{tel\, que}\,Condition(x)\}finkitxmlcodeinlinelatexdvp.

Exemples :

 
Sélectionnez
>>> liste = [x**2 for x in liste if (x % 2 == 0)] # Carrés des éléments pairs
>>> print liste
[0, 4, 16, 36, 64]
  • Liste des multiples de 12 entre 0 et 100 :
 
Sélectionnez
>>> liste = [x for x in range(101) if x % 12 == 0] # Multiples de 12
>>> print liste
[0, 12, 24, 36, 48, 60, 72, 84, 96]
  • Liste des diviseurs d'un entier naturel n :
 
Sélectionnez
>>> n = 120
>>> diviseurs = [x for x in range(1,n+1) if (n % x == 0)] # Diviseurs de n
>>> print diviseurs
[1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120]

On peut réécrire la méthode des trapèzes précédenteExemple 3 : calcul intégral - méthode des trapèzes en utilisant une liste en compréhension :

 
Sélectionnez
def trapeze2(f, a, b, n):    # version 2 avec liste en compréhension
    if a > b :
        return -trapeze2(f, b, a, n)     
    pas = (b-a) / float(n)
    res = (f(a)+f(b)) / 2.
    res += sum([f(a + k*pas) for k in range(1,n)])
    res *= pas
    return res

précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 Jean-Philippe PREAUX. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.