Aller au contenu

Créer et modifier des listes

Objet mutable

On connaît jusqu'à présent trois types itérables : le type list, le type tuple, et le type str.

🐍 Code Python
1
2
3
4
iter1 = 1, 2, 3 
iter2 = (1, 2, 3) 
iter3 = [1, 2, 3]
iter4 = "123"
 

Remarque. On observe dans la console :

⚙️ Résultat
>>> 1, 2, 3
(1, 2, 3)

Ainsi iter1 et iter2 sont rigoureusement identiques.

iter1 (et iter2) ont pour type tuple, iter3 a pour type list, et iter4 a pour type str.

On peut donc en parcourir les éléments à l'aide d'une boucle for (par indice ou par valeur), et accéder à l'élément d'indice i d'iterable avec la syntaxe iterable[i].

Il est possible de modifier en place la valeur d'un élément dans une liste. Cela se fait à l'aide d'une affectation, comme dans l'exemple ci-dessous.

🐍 Code Python
1
2
3
4
notes = [9, 11, 15]    
notes[0] # s'évalue en 9
notes[0] = 10
print(notes) # l'élément d'indice 0 a été modifié
⚙️ Résultat
[10, 11, 15]

Cependant, il n'est pas possible de réaliser cette opération sur des objets de type tuple ou str.

🐍 Code Python
1
2
3
notes = (9, 11, 15)
notes[0] # s'évalue en 9
notes[0] = 10
⚙️ Résultat
TypeError Traceback (most recent call last)
Cell In[386], line 3
      1 notes = (9, 11, 15)
      2 notes[0] # s'évalue en 9
----> 3 notes[0] = 10
      4 print(notes)

TypeError: 'tuple' object does not support item assignment
 
🐍 Code Python
1
2
3
prenom = "drédéric"    
prenom[0] # s'évalue en "d"
prenom[0] = "f"
⚙️ Résultat
TypeError Traceback (most recent call last)
Cell In[401], line 3
      1 prenom = "drédéric"    
      2 prenom[0] # s'évalue en "d"
----> 3 prenom[0] = "f"

TypeError: 'str' object does not support item assignment

On dit que les objets de type list sont des objets mutables, tandis que les objets de type tuple et str sont des objets non mutables.

Modification en place d'une liste

Notes arrondies

Un professeur de NSI enseignant au lycée Fustel utilise un programme python pour gérer les notes de ses élèves. Il dispose d'une liste notes de flottants :

🐍 Code Python
1
notes = [16.5, 9.9, 6.4, 7.8, 11.7, 15.4]    

À la fin d'un cours, inquiet de ce qu'il voit sur pronote, un élève vient voir le professeur et lui dit qu'il n'a pas obtenu 6.4 au contrôle de NSI mais bien 16.4 !

Écrire l'instruction python qui permet de modifier la variable notes afin de corriger le problème.

Dans sa grande magnanimité, ce professeur de NSI décide d'arrondir les notes au demi-point supérieur. Ainsi, la note de 16.5 sera arrondie à 17, mais la note de 15.4 sera arrondie à 15.5.

Écrire une fonction python arrondir_notes qui prend en argument une liste de notes et qui modifie en place les notes de la liste en les arrondissant au demi-point supérieur.

Indication. Si a est un flottant, alors a%1 représente la partie fractionnaire de a, et a//1 est sa partie entière. Par exemple :

⚙️ Résultat
>>> a = 14.25
>>> a % 1
0.25
>>> a // 1
14.0
🐍 Code Python
1
2
3
4
def arrondir_notes(notes):
    """ [float] -> None
    Arrondi les notes au demi-point supérieur """
    pass
  1. notes est la liste [10, 11, 12].

    1. Comment est modifié la liste notes après l'exécution de arrondir_notes(notes) ? Ce comportement est-il souhaitable ?

    2. Modifier la fonction arrondir_notes afin de corriger ce problème.

  2. notes est le tuple (10, 11, 12).

    Que se passe-t-il lorsque l'on exécute l'instruction arrondir_notes(notes) ? À quoi ce problème est-il dû ?

Appliquer une réduction aux éléments d'un panier

Au supermarché Dôvv, la gérante est très satisfaite par le programme permettant de calculer le prix à payer par le client. Elle souhaiterait voir implémentée une nouvelle fonctionnalité afin de pouvoir gérer les réductions sur certains articles.

Par exemple on peut avoir :

🐍 Code Python
1
2
3
objets = ["pomme", "ananas", "prune"]
reduction = [10, 5, 50]
prix = [100, 500, 50]

:space 1em

Cela signifie que les pommes, initialement à 100 francs l'unité, voient leur prix diminuer de $10\%$. Le prix des ananas est lui diminué de $5\%$, le prix des prunes est diminué de $50\%$.

Écrire une fonction applique_reduction qui prend en argument une liste prix et une liste reduction et qui modifie en place les éléments de la liste prix pour leur appliquer le pourcentage de réduction correspondant. Les nouveaux prix seront arrondis à l'entier inférieur.

Rappel. On rappelle que pour diminuer un prix $p$ de $t\%$ on utilise la formule $p\times \left(1 - \dfrac{t}{100}\right)$.

🐍 Code Python
1
2
3
4
5
def applique_reduction(prix, reductions):
    """ [int], [int] -> None
    prix et reductions sont deux listes de même taille
    Modifie la liste prix en place pour leur appliquer la réduction correspondante """
    pass

Création de listes en compréhension

Jusqu'à présent on a créé des listes en extension. C'est à dire que l'on a listé de manière exhaustive, "à la main", tous les éléments de la liste les uns après les autres. Par exemple [1, 2, 3].

En python comme en mathématiques, il est possible de créer des listes en compréhension, c'est à dire, non pas de donner les éléments, mais de donner une manière de calculer les éléments de la liste.

  • Entiers inférieurs ou égaux à 5.

    ⚙️ Résultat
    >>> [i for i in range(6)]
    [0, 1, 2, 3, 4, 5]
    
  • Table de multiplication (partielle) de 3.

    ⚙️ Résultat
    >>> [3*i for i in range(7)]
    [0, 3, 6, 9, 12, 15, 18]
    
  • Une liste de 8 zéros.

    ⚙️ Résultat
    >>> [0 for i in range(8)]
    [0, 0, 0, 0, 0, 0, 0, 0]
    
  • La liste des 5 premiers nombres au carré.

    ⚙️ Résultat
    >>> [i**2 for i in range(5)]
    [0, 1, 4, 9, 16]
    

Dans cet exercice, on a déjà exécuté l’instruction : t = [42, 23, 2, 3, −50].

Donner les listes créées par ces listes en compréhension :

  1. [0 for v in t]
  2. [v for v in t if v >= 10]
  3. [i for i in range(len(t)) if (t[i] % 2) == 1]
  4. [ch[0] for ch in ["Ada", "Alice", "Bob", "Eve"]]
  5. [i % 10 for i in range(9, 12)]
  6. [i % 10 for i in range(55) if (i // 50) == 1]
  7. [i for i in range(len(t)) if t[i] == i]

Copier une liste : phénomène d'aliasing

Considérons les instructions suivantes :

⚙️ Résultat
>>> liste1 = [1, 2, 3]
>>> liste2 = liste1
>>> liste1[0] = 10
  1. Recopier ces instructions dans la console.

    Qu'affiche l'instruction print(liste2) ? Commenter.

  2. Écrire une fonction copie_independante qui prend en argument une liste et qui recopie dans une nouvelle liste tous les éléments de liste dans le même ordre avant de la renvoyer.

Correction

🐍 Code Python
1
2
3
4
def copie_independante(liste):
    """ [int] -> [int]
    Créé une copie indépendante de liste """
    return [e for e in liste]
🐍 Code Python
1
2
3
4
def copie_independante(liste):
    """ [int] -> [int]
    Créé une copie indépendante de liste """
    pass

Ajouter un élément à une liste

Écrire une fonction ajoute_fin qui prend en argument une liste et un élément e et qui renvoie une copie indépendante de liste dans laquelle l'élément e a été ajouté à la fin.

🐍 Code Python
1
2
3
4
def ajoute_fin(liste, e):
    """ [int], int -> [int]
    Renvoie une liste constituée des éléments de l suivis de e """
    pass
🐍 Code Python
1
2
3
4
5
l = [1, 2, 3]
print(ajoute_fin(l, 4))
print(l)
l = ajoute_fin(l, 8)
print(l)
⚙️ Résultat
[1, 2, 3, 4]
[1, 2, 3]
[1, 2, 3, 8]
  1. Justifier les affichages produits par les lignes 2, 3, et 5 du code ci-dessus.
  2. Challenge. Écrire une fonction ajoute_pos qui prend en argument une liste liste, un élément e et un indice i et qui renvoie la liste constituée des éléments de liste dans laquelle on a inséré l'élément e à l'indice i (les éléments de liste d'indice supérieur ou égal à i sont donc décalés vers la droite).

    🐍 Code Python
    1
    2
    3
    4
    5
    def ajoute_pos(liste, e, i):
        """ [int], int, int -> [int]
        0 <= i <= len(liste)
        Renvoie une liste indépendante de l dans laquelle l'élément e a été inséré à l'indice i """
        pass
    

Supprimer un élément d'une liste

Écrire une fonction supprime_pos qui prend en argument une liste et un indice i compatible avec la taille de la liste et qui renvoie une liste indépendante constituée des éléments de liste dans laquelle l'élément d'indice i de liste n'apparaît pas.

🐍 Code Python
1
2
3
4
5
def supprime_pos(liste, i):
    """ [int], int -> [int]
    0 <= i < len(liste)
    Supprime l'élément d'indice i de liste ""
    pass
🐍 Code Python
1
2
3
4
liste = [1, 2, 3]    
print(supprime_pos(liste, 0))
print(supprime_pos(liste, 1))
print(supprime_pos(liste, 2))
⚙️ Résultat
[2, 3]
[1, 3]
[1, 2]

Renverser une liste

Écrire une fonction renverse qui prend en argument une liste et qui renvoie une liste dont les éléments sont ceux de liste lus de droite à gauche.

🐍 Code Python
1
2
3
4
def renverse(liste):
    """ [int] -> [int]
    Renvoie une liste dont les éléments sont ceux de liste lus de droite à gauche """
    pass

Indication. La documentation officielle indique via help(range) :

⚙️ Résultat
class range(object)
range(stop) -> range object
range(start, stop[, step]) -> range object

Return an object that produces a sequence of integers from start
(inclusive) : to stop (exclusive) by step.  range(i, j) produces
i, i+1, i+2, ..., j-1. start defaults to 0, and stop is omitted!
range(4) produces 0, 1, 2, 3. These are exactly the valid indices
for a list of 4 elements.  When step is given, it specifies
the increment (or decrement).
🐍 Code Python
1
2
3
l = [1, 2, 3]
print(renverse(l))
print(l)
⚙️ Résultat
[3, 2, 1]
[1, 2, 3]

Liste des indices des occurrences d'un élément dans un tableau

Dans cette partie, on souhaite écrire une fonction indices_occurrences qui renvoie la liste des indices des occurrences de e dans la liste. Si e n'est pas présent dans liste alors la fonction renvoie la liste vide [].

  1. Rappeler le code de la fonction nombre_occurrences qui prend en argument une liste et un élément e et qui renvoie le nombre de fois que l'élément e apparaît dans la liste (son nombre d'occurrences).
  2. liste est la liste [1, 1, 3, 1, 3, 2]. Que doit renvoyer :

    1. indices_occurrences(liste, 1)
    2. indices_occurrences(liste, 2)
    3. indices_occurrences(liste, 3)
    4. indices_occurrences(liste, 4)

On propose trois implémentations différentes pour la fonction indices_occurrences.

Compléter les codes correspondant à la description de l'énoncé. Tester chacune des fonctions.

Implémentation 1.

Pour déterminer la liste des occurrences de e dans liste, on initialise une liste l de bonne taille (elle contiendra les indices de chaque occurrence de e), et un entier i qui servira à mémoriser où on doit stocker dans l l'indice de la prochaine occurrence de e. On parcourt liste par indice : si l'élément d'indice k de liste est une occurrence de e, alors on stocke k à l'indice i de l et on incrémente i.

img

🐍 Code Python
1
2
3
4
5
6
7
8
9
def indices_occurrences(liste, e):
    n = nombre_occurrences(liste, e)
    l = [0 for i in ...]
    i = 0
    for k in range(liste):
        if ...:
            ...
            ...
    return ...

Implémentation 2.

On fait appel à la fonction ajoute_fin pour ajouter successivement les indices des occurrences de e à la liste l, sans chercher à connaître au préalable le nombre d'occurrences de e.

img

🐍 Code Python
1
2
3
4
5
6
def indices_occurrences(liste, e):
    l = []
    for k in range(liste):
        if ...:
            ...
    return ...

Implémentation 3.

On détermine directement les indices des occurrences de e dans l à l'aide d'une liste en compréhension et d'un filtrage.

img

🐍 Code Python
1
2
def indices_occurrences(liste, e):
    return [...]