ANTISECHE
Pour ne plus rien oublier !

Copier ou dupliquer une liste de plus d’une dimension en Python

mercredi 12 juin 2013

Contexte

Lorsque l’on traduit son algorithme en langage informatique et que l’on est concentré sur l’efficacité de son algorithme on peut parfois oublier une spécificité du langage informatique qui fait que votre algorithme ne fonctionnera pas. Et bien évidement, votre premier réflexe est de revoir votre algorithme et de passer des heures et des heures avant de vous rendre enfin compte que finalement, le problème ne viendrait peut être pas de votre algorithme.

Un peu de théorie

Habituellement, en Python, lorsque vous souhaitez copier une variable vous faîtes simplement :

a = 9
b = a
a = 10
print(a)
10
Print(b)
9

Et dans ce cas tout fonctionne parfaitement. Cependant, tout ne fonctionne pas exatement de la même façon pour tous les types de variables. Exemple :

a = [9]
b = a
a[0] = 10
print(a)
[10]
print(b)
[10]

Comme vous pouvez le voir assigner à une nouvelle liste une liste déjà existante ne la duplique pas mais donne tout simplement une deuxième porte d’accès à cette liste. Python réagit comme ça afin de limiter l’impacte mémoire du programme.

Si vous souhaitez réellement dupliquer une liste, deux solutions s’offrent à vous. Tout d’abord, l’utilisation d’un slice :

a = [9]
b = a[:]
a[0] = 10
print(a)
[10]
print(b)
[9]

Je trouve cette méthode moins jolie. Je préfère utiliser la deuxième solution que je trouve plus pythonique, à savoir :

a = [9]
b = list(a)
a[0] = 10
print(a)
[10]
print(b)
[9]

Et voilà, vous vous retrouvez avec deux listes complètement distinctes.

Ce qu'il s’est passé

Mais voilà, en général ça marche bien. Mais là hier, ça ne voulait rien savoir, ça ne marchait pas. J’ai passé plus de 3 heures à remettre en question mon algorithme qui, une fois en Python, ne voulait pas faire ce qu’il était sensé faire. Et puis, en regardant de plus près, je vois ça :

a = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
b = list(a)

Je voulais dupliquer une liste de dimension supérieure à 1, mais Python lui, ne le voyait pas de cette façon là. Et pour cause… List() et [:] ne sont pas récursifs. Ce qui veut dire qu’ils ne vont dupliquer que la liste de premier niveau et pas les listes qu’elle peut elle-même contenir. Tout ça pour ça… 3 heures…

La solution

Et bien la solution est simple, il est nécessaire de passer par la fonction deepcopy(). Cette fonction permet de copier tout object et les objects qu’il peut imbriquer.

from copy import deepcopy
a = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
b = deepcopy(a)

Et voilà, nous nous retrouvons bien avec deux listes bien distinctes mais identiques.

Aucun commentaire

Fil RSS des commentaires de cet article

Écrire un commentaire

Contenu de votre message :

Votre nom ou pseudo :

Votre site Internet (facultatif) :

Votre adresse e-mail (facultatif) :

Quelle est la troisième lettre du mot boyl ? : 

CopyLeft - 2013-17 - Toutes gauches réservées - Licence CC-BY

Valide xHtml 1.0 STRICT | Fièrement propulsé par PluXml | 0.018s | 2947 vues