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.

1 commentaire

#1 lundi 29 octobre 2018 à 08:20 nonton indoxxi a dit :

Hey I know this is off topic but I was wondering if you
knew of any widgets I could add to my blog that automatically tweet my newest twitter updates.
I've been looking for a plug-in like this for quite some time and was hoping
maybe you would have some experience with something like this.

Please let me know if you run into anything. I truly enjoy
reading your blog and I look forward to your new updates.

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 deuxième lettre du mot smgg ? : 

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

Valide xHtml 1.0 STRICT | Fièrement propulsé par PluXml | 0.023s | 10643 vues