Aller au contenu

Copier un tableau

Plusieurs étiquettes sur un tableau

Puisque les objets de type list sont muables, le symbole d'affectation « = » permet-il de copier le contenu d'un tableau dans une autre variable ?

Pour répondre à cette question, on considère les instructions suivantes :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
>>> a = [2, 3, 4, 5, 6]

>>> b = a

>>> c = [2, 3, 4, 5, 6]

>>> b[len(b)-1] = 666

>>> a[0] = 42

>>> a

>>> b

>>> c
  1. Anticipez le contenu des tableaux a, b et c dans les dernières lignes.

    Affichages
    >>> a = [2, 3, 4, 5, 6]
    
    >>> b = a
    
    >>> c = [2, 3, 4, 5, 6]
    
    >>> b[len(b)-1] = 666
    
    >>> a[0] = 42
    
    >>> a
    [42, 3, 4, 5, 666]
    
    >>> b
    [42, 3, 4, 5, 666]
    
    >>> c
    [2, 3, 4, 5, 6]
    
  2. Cherchez à expliquer ces résultats avant de consulter les explications ci-dessous.

    Explications des lignes 1 à 5
    • En ligne 1, l'objet de type list et de valeur [2, 3, 4, 5, 6] est construit puis on lui attribue l'étiquette a :
    • En ligne 3, b = a a pour effet de coller une seconde étiquette sur l'objet de type list précédent.
    • En ligne 5, un nouvel objet de type list et de valeur [2, 3, 4, 5, 6] est construit puis on lui attribue l'étiquette c : Attention, le contenu de c est le même que celui de a, mais le conteneur n'est pas le même (on a deux bouteilles contenant chacune un litre de lait, mais il y a bien deux bouteilles différentes).
    Explications des lignes 7 et 9
    • En ligne 7, on modifie le contenu de l'objet list étiqueté b :

    Cet objet porte aussi l'étiquette a donc l'effet aurait été le même avec l'instruction a[len(a)-1] = 666.

    • En ligne 9, on modifie le contenu de l'objet list étiqueté a :

    Cet objet porte aussi l'étiquette b donc l'effet aurait été le même avec l'instruction b[0] = 42.

    • Dans les lignes suivantes, on voit que les modifications faites sur a l'ont été aussi sur b. Le tableau c quant à lui reste inchangé (il s'agit bien d'une autre bouteille).
    Avec Python Tutor

    Le site Python tutor permet de visualiser qu'un objet peut disposer de plusieurs noms (étiquettes) :

Un objet a-t-il plusieurs étiquettes ?

Méthode

Pour vérifier si deux noms de variables (deux étiquettes) désignent le même objet, on peut utiliser l'opérateur is en Python.

Copiez/collez/exécutez les instructions suivantes afin de comprendre le rôle de cet opérateur :

>>> a = [2, 3, 4, 5, 6]

>>> b = a

>>> c = [2, 3, 4, 5, 6]

>>> a == b
True

>>> a is b
True

>>> a == c     # même contenu
True

>>> a is c     # bouteille différente
False
Pour aller plus loin

En Python, toutes les variables, quel que soit leur type, sont des objets. Contrairement à d'autres langages de programmation (comme le C ou le Java), le choix a été fait d'un typage dynamique pour rendre la manipulation de ces objets plus « facile ». En contrepartie, dans le cas d'un objet complexe, muable et donc potentiellement lourd en mémoire, c'est l'action la plus rapide qui est privilégiée par le langage.

Le type list fait partie de ces objets potentiellement lourds.
Pour éviter une occupation mémoire inutile, l'affectation « = » crée une nouvelle étiquette (on parle « d'alias ») pour le tableau plutôt qu'un nouveau tableau.

Copie de tableau

Exemple

On a saisi les instructions ci-dessous dans la console afin que le tableau L1 contienne les entiers successifs de 0 à 10 tandis que le tableau L2 contienne les entiers successifs de 0 à 9 suivis de 11. Est-ce le cas ?

>>> L1 = list(range(11))

>>> L2 = L1

>>> L2[10] = 11
Réponse

Bien évidemment, ce n'est pas le cas puisque l'instruction L2 = L1 ne fait qu'ajouter une étiquette au même tableau. Par conséquent, l'instruction L2[10] = 11 s'applique au même tableau d'étiquettes L1 et L2.
Ajoutons des lignes pour s'en convaincre :

>>> L1 = list(range(11))

>>> L1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> L2 = L1

>>> L2[10] = 11

>>> L2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

>>> L1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

Cet exemple montre qu'il faut faire attention lorsqu'on souhaite copier un tableau dans une autre variable. Plusieurs solutions sont possibles dans le cas de tableaux simples, c'est-à-dire d'un tableau qui ne contient pas lui-même des tableaux.

Méthodes pour copier un tableau « simple »

  1. La copie en utilisant la fonction list() :

    >>> L2 = list(L1)
    

  2. La copie par compréhension :

    >>> L2 = [element for element in L1]
    

  3. La copie élément par élément à l'aide d'une fonction :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def copie(tab):
        """
        tab - list
        Sortie: list - Renvoie un tableau de même contenu que tab
        """
        nouv_tab = []
        for element in tab:
            nouv_tab.append(element)
        return nouv_tab
    
    puis
    >>> L2 = copie(L1)
    

    Explications

    Voyons un peu le détail avec l'appel suivant :

    L = [3, 4, 2, 1]
    T = copier(L)
    

    L'instruction L = [3, 4, 2, 1] conduit à la situation : Copie 01

    Dans l'instruction suivante T = copier(L), la priorité est l'appel à la fonction copier() (partie droite de l'instruction d'affectation).
    La situation devient : Copie 02

    La ligne 6 du programme (nouv_tab = []) est ensuite exécutée : Copie 03

    Puis on exécute les lignes 7 et 8 : Copie 04

    Enfin la fonction renvoie le tableau nouv_tab et on l'affecte à l'étiquette T : Copie 05

  4. La copie en important la fonction copy() contenue dans le module copy :

    >>> from copy import copy
    
    >>> L2 = copy(L1)