2008-10-08 13 views
47

Quelle est la meilleure façon de copier une liste? Je connais les moyens suivants, lequel est le meilleur? Ou y a-t-il un autre moyen?Quel est le meilleur moyen de copier une liste?

lst = ['one', 2, 3] 

lst1 = list(lst) 

lst2 = lst[:] 

import copy 
lst3 = copy.copy(lst) 

Répondre

86

Si vous voulez une copie superficielle (éléments ne sont pas copiés) utilisent:

lst2=lst1[:] 

Si vous souhaitez effectuer une copie en profondeur puis utilisez le module de copie:

import copy 
lst2=copy.deepcopy(lst1) 
+1

Que voulez-vous dire par les éléments ne sont pas copiés? – sheats

+4

Si les éléments sont des objets mutables ils sont passés par référence, vous devez utiliser deepcopy pour vraiment les copier. –

+2

Copier uniquement les références contenues dans la liste. Si un élément de la liste contient une référence à un autre objet, cela ne sera pas copié. 9 fois sur 10 vous avez juste besoin de la copie superficielle. –

18

J'utilise souvent:

lst2 = lst1 * 1 

Si lst1 il contient d'autres conteneurs (comme les autres listes), vous devriez utiliser deepcopy de la bibliothèque de copie comme indiqué par Mark.


MISE À JOUR: Expliquer deepcopy

>>> a = range(5) 
>>> b = a*1 
>>> a,b 
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4]) 
>>> a[2] = 55 
>>> a,b 
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4]) 

Comme vous pouvez le voir seulement changé ... Je vais essayer maintenant avec une liste de listes

>>> 
>>> a = [range(i,i+3) for i in range(3)] 
>>> a 
[[0, 1, 2], [1, 2, 3], [2, 3, 4]] 
>>> b = a*1 
>>> a,b 
([[0, 1, 2], [1, 2, 3], [2, 3, 4]], [[0, 1, 2], [1, 2, 3], [2, 3, 4]]) 

Pas si facile à lire, permettez-moi de l'imprimer avec un pour:

>>> for i in (a,b): print i 
[[0, 1, 2], [1, 2, 3], [2, 3, 4]] 
[[0, 1, 2], [1, 2, 3], [2, 3, 4]] 
>>> a[1].append('appended') 
>>> for i in (a,b): print i 

[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]] 
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]] 

Vous voyez ça? Il est aussi ajouté à b [1], donc b [1] et a [1] sont exactement le même objet. Maintenant, essayez avec deepcopy

>>> from copy import deepcopy 
>>> b = deepcopy(a) 
>>> a[0].append('again...') 
>>> for i in (a,b): print i 

[[0, 1, 2, 'again...'], [1, 2, 3, 'appended'], [2, 3, 4]] 
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]] 
+2

'copy()' ne fonctionnera pas dans le dernier cas, vous avez besoin de 'deepcopy()' chaque fois que vous avez une référence dans l'objet. –

+1

Je pensais que votre truc d'utiliser 'lst1 * 1' était vraiment sympa ... mais, malheureusement, le profilage grossier suggère qu'il est au moins deux fois plus lent que' lst1 [:] ', qui est légèrement plus rapide que' copy (last1) '. – Andrew

2

Vous pouvez aussi le faire:

import copy 
list2 = copy.copy(list1) 

Cela devrait faire la même chose que copie superficielle de Mark Roddy.

12

Vous pouvez également faire:

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

Le résultat est-il une copie peu profonde ou profonde? – minty

+8

Non, l'utilisation de list() est définitivement une copie superficielle. Essaye le. –

+2

Y a-t-il une différence de vitesse? Sans doute, quand vous faites '[:]', la librairie est assez intelligente pour savoir qu'une copie est faite et donc elle pourrait invoquer du code C natif pour le faire. Avec 'list (itérable)' sait-il/se soucie-t-il que l'itérable est déjà matérialisée et peut donc être copiée efficacement? –

6

J'aime faire:

lst2 = list(lst1) 

L'avantage par rapport lst1 [:] est que le même fonctionne idiome pour dicts:

dct2 = dict(dct1) 
+0

Il y avait en fait une assez longue discussion sur la copie du dictionnaire par rapport à la liste de diffusion sur la liste de diffusion Python 3K: http://mail.python.org/pipermail/python-3000/2008-February/thread.html#12052 –

+0

un peu d'info ici est que pour les dictionnaires, vous pouvez faire d = d.copy() –

0

En termes de performances, il y a une surcharge pour appeler list() par rapport à la découpe. Donc, pour les listes courtes, lst2 = lst1[:] est environ deux fois plus rapide que lst2 = list(lst1).

Dans la plupart des cas, cela est probablement compensé par le fait que list() est plus lisible, mais dans les boucles serrées ceci peut être une optimisation valable.

3

listes courtes, [:] est le meilleur:

In [1]: l = range(10) 

In [2]: %timeit list(l) 
1000000 loops, best of 3: 477 ns per loop 

In [3]: %timeit l[:] 
1000000 loops, best of 3: 236 ns per loop 

In [6]: %timeit copy(l) 
1000000 loops, best of 3: 1.43 us per loop 

Pour les listes plus grandes, ils sont tous sur le même:

In [7]: l = range(50000) 

In [8]: %timeit list(l) 
1000 loops, best of 3: 261 us per loop 

In [9]: %timeit l[:] 
1000 loops, best of 3: 261 us per loop 

In [10]: %timeit copy(l) 
1000 loops, best of 3: 248 us per loop 

Pour les listes très grandes (j'ai essayé 50MM), ils sont toujours à peu près les mêmes.

+0

Je ne voudrais pas déranger si je dois faire une seule copie entre 100s de lignes de code. Seulement si c'est une partie de base de l'application et la copie de liste est fréquente, je pourrais déranger. – Saurabh

Questions connexes