Comment cloner ou copier une liste?
18 réponses
avec new_list = my_list
, vous n'avez pas deux listes. La cession ne fait que Copier la référence à la liste, et non à la liste proprement dite, de sorte que new_list
et my_list
renvoient toutes deux à la même liste après la cession.
pour réellement copier la liste, vous avez diverses possibilités:
-
vous pouvez utiliser la méthode intégrée
list.copy()
(disponible depuis python 3.3):new_list = old_list.copy()
-
, Vous pouvez le couper en tranches:
new_list = old_list[:]
L'opinion D'Alex Martelli (au moins retour en 2007 ) à ce sujet est, que c'est une syntaxe étrange et il n'a pas de sens de l'utiliser jamais . ;) (À son avis, la suivante est plus lisible).
-
vous pouvez utiliser le construit dans
list()
fonction:new_list = list(old_list)
-
vous pouvez utiliser du générique
copy.copy()
:import copy new_list = copy.copy(old_list)
c'est un peu plus lent que
list()
parce qu'il faut d'abord trouver le type de données deold_list
. -
si la liste contient des objets et que vous voulez les copier, utilisez
copy.deepcopy()
:import copy new_list = copy.deepcopy(old_list)
évidemment la méthode la plus lente et la plus besoin de mémoire, mais parfois inévitable.
exemple:
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return str(self.val)
foo = Foo(1)
a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print('original: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
% (a, b, c, d, e, f))
résultat:
original: ['foo', 5, 'baz']
list.copy(): ['foo', 5]
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]
Félix a déjà fourni une excellente réponse, mais j'ai pensé que je ferais une comparaison de vitesse des différentes méthodes:
- de 10,59 sec (105.9 us/mii) -
copy.deepcopy(old_list)
- 10.16 sec (101.6 us / itn) - pur python
Copy()
méthode classes de copie avec deepcopy - 1.488 sec (14.88 us / itn) - Python pur
Copy()
méthode ne copiant pas les classes (seulement dicts/listes/tuples) - 0,325 sec (3.25 us / itn) -
for item in old_list: new_list.append(item)
- 0.217 sec (2.17 us / itn) -
[i for i in old_list]
(a list understanding ) - 0.186 sec (1.86 us / itn) -
copy.copy(old_list)
- 0,075 sec (0,75 us/itn) -
list(old_list)
- en 0.053 s (0.53 us/itn) -
new_list = []; new_list.extend(old_list)
- en 0.039 s (0.39 us/itn) -
old_list[:]
( liste de découpage )
donc le plus rapide est le listing. Mais sachez que copy.copy()
, list[:]
et list(list)
, contrairement à copy.deepcopy()
et à la version python ne copient pas de listes, dictionnaires et instances de classe dans la liste, donc si les originaux changent, ils changeront aussi dans la liste copiée et vice versa.
(Voici le script si quelqu'un est intéressé ou veut soulever des questions:)
from copy import deepcopy
class old_class:
def __init__(self):
self.blah = 'blah'
class new_class(object):
def __init__(self):
self.blah = 'blah'
dignore = {str: None, unicode: None, int: None, type(None): None}
def Copy(obj, use_deepcopy=True):
t = type(obj)
if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False
# Copy each item recursively
for x in xrange(len(obj)):
if type(obj[x]) in dignore:
continue
obj[x] = Copy(obj[x], use_deepcopy)
if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)
elif t == dict:
# Use the fast shallow dict copy() method and copy any
# values which aren't immutable (like lists, dicts etc)
obj = obj.copy()
for k in obj:
if type(obj[k]) in dignore:
continue
obj[k] = Copy(obj[k], use_deepcopy)
elif t in dignore:
# Numeric or string/unicode?
# It's immutable, so ignore it!
pass
elif use_deepcopy:
obj = deepcopy(obj)
return obj
if __name__ == '__main__':
import copy
from time import time
num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},
old_class(), new_class()]
t = time()
for i in xrange(num_times):
Copy(L)
print 'Custom Copy:', time()-t
t = time()
for i in xrange(num_times):
Copy(L, use_deepcopy=False)
print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t
t = time()
for i in xrange(num_times):
copy.copy(L)
print 'copy.copy:', time()-t
t = time()
for i in xrange(num_times):
copy.deepcopy(L)
print 'copy.deepcopy:', time()-t
t = time()
for i in xrange(num_times):
L[:]
print 'list slicing [:]:', time()-t
t = time()
for i in xrange(num_times):
list(L)
print 'list(L):', time()-t
t = time()
for i in xrange(num_times):
[i for i in L]
print 'list expression(L):', time()-t
t = time()
for i in xrange(num_times):
a = []
a.extend(L)
print 'list extend:', time()-t
t = time()
for i in xrange(num_times):
a = []
for y in L:
a.append(y)
print 'list append:', time()-t
t = time()
for i in xrange(num_times):
a = []
a.extend(i for i in L)
print 'generator expression extend:', time()-t
EDIT : ajout de classes et de dicts New-style, old-style aux benchmarks, et rendu la version de python beaucoup plus rapide et ajouté plus de méthodes dont les expressions list et extend()
.
j'ai on m'a dit que Python 3.3+ ajoute list.copy()
méthode, qui devrait être aussi rapide que le tranchage:
newlist = old_list.copy()
quelles sont les options pour cloner ou copier une liste en Python?
en Python 3, une copie superficielle peut être faite avec:
a_copy = a_list.copy()
en Python 2 et 3, vous pouvez obtenir une copie peu profonde avec une pleine tranche de l'original:
a_copy = a_list[:]
explication
il y a deux façons sémantiques de copier une liste. Une copie superficielle crée une nouvelle liste des mêmes objets, une copie profonde crée une nouvelle liste contenant de nouveaux objets équivalents.
Superficielle de la liste de copie
une copie superficielle ne copie que la liste elle-même, qui est un conteneur de références aux objets de la liste. Si les objets contenus eux-mêmes sont mutables et qu'un est modifié, le changement sera reflété dans les deux listes.
il y a différentes façons de faire ceci en Python 2 et 3. Le Python 2 ways fonctionne aussi en Python 3.
Python 2
en Python 2, la façon idiomatique de faire une copie superficielle d'une liste est avec une tranche complète de l'original:
a_copy = a_list[:]
vous pouvez également accomplir la même chose en passant la liste par le constructeur de liste,
a_copy = list(a_list)
mais l'utilisation du constructeur est moins efficace:
>>> timeit
>>> l = range(20)
>>> min(timeit.repeat(lambda: l[:]))
0.30504298210144043
>>> min(timeit.repeat(lambda: list(l)))
0.40698814392089844
Python 3
en Python 3, les listes list.copy
méthode:
a_copy = a_list.copy()
En Python 3.5:
>>> import timeit
>>> l = list(range(20))
>>> min(timeit.repeat(lambda: l[:]))
0.38448613602668047
>>> min(timeit.repeat(lambda: list(l)))
0.6309100328944623
>>> min(timeit.repeat(lambda: l.copy()))
0.38122922903858125
de Faire un autre pointeur n' pas créer une copie
en utilisant new_list = my_list modifie ensuite new_list à chaque fois que my_list change. Pourquoi est-ce?
my_list
est juste un nom qui pointe vers la liste actuelle en mémoire. Quand vous dites new_list = my_list
vous ne faites pas une copie, vous ajoutez juste un autre nom qui pointe sur cette liste originale en mémoire. Nous pouvons avoir des problèmes similaires lorsque nous faisons des copies de listes.
>>> l = [[], [], []]
>>> l_copy = l[:]
>>> l_copy
[[], [], []]
>>> l_copy[0].append('foo')
>>> l_copy
[['foo'], [], []]
>>> l
[['foo'], [], []]
la liste est juste un tableau de pointeurs vers le contenu, donc une copie superficielle copie juste les pointeurs, et donc vous avez deux listes différentes, mais ils ont le même contenu. Faire des copies du contenu, vous avez besoin d'une copie en profondeur.
Profonde copies
pour faire une copie profonde d'une liste, en Python 2 ou 3, Utilisez deepcopy
dans le copy
module :
import copy
a_deep_copy = copy.deepcopy(a_list)
pour montrer comment cela nous permet de faire de nouvelles sous-listes:
>>> import copy
>>> l
[['foo'], [], []]
>>> l_deep_copy = copy.deepcopy(l)
>>> l_deep_copy[0].pop()
'foo'
>>> l_deep_copy
[[], [], []]
>>> l
[['foo'], [], []]
et donc nous voyons que la liste profonde copiée est une liste entièrement différente de l'original. Vous pourriez jouer votre propre rôle, mais ne le faites pas. Vous êtes susceptible de créer des bogues que vous n'auriez pas autrement en utilisant le standard la fonction d'analyse approfondie de la bibliothèque.
Ne pas utiliser eval
vous pouvez voir cela utilisé comme un moyen de la profonde, mais ne le faites pas:
problematic_deep_copy = eval(repr(a_list))
- c'est dangereux, surtout si vous évaluez quelque chose d'une source en laquelle vous n'avez pas confiance.
- ce n'est pas fiable, si un sous-élément que vous copiez n'a pas de représentation qui peut être évaluée pour reproduire un élément équivalent.
- c'est aussi moins performant.
en python 64 bits 2.7:
>>> import timeit
>>> import copy
>>> l = range(10)
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
27.55826997756958
>>> min(timeit.repeat(lambda: eval(repr(l))))
29.04534101486206
sur 64 bits Python 3.5:
>>> import timeit
>>> import copy
>>> l = list(range(10))
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
16.84255409205798
>>> min(timeit.repeat(lambda: eval(repr(l))))
34.813894678023644
il y a déjà beaucoup de réponses qui vous disent comment faire une copie correcte, mais aucune d'entre elles ne dit Pourquoi votre 'copie' originale a échoué.
Python ne stocke pas de valeurs dans les variables; il lie les noms aux objets. Votre affectation d'origine a pris l'objet référencé par my_list
et lié à new_list
. Quel que soit le nom que vous utilisez, il n'y a toujours qu'une seule liste, donc les changements apportés lorsque vous faites référence à my_list
persisteront lorsque vous faites référence à my_list
. new_list
. Chacun des autres réponses à cette question vous donne différentes façons de créer un nouvel objet à lier à new_list
.
chaque élément d'une liste agit comme un nom, en ce que chaque élément se lie non exclusivement à un objet. Une copie crée une nouvelle liste dont les éléments se lient aux mêmes objets comme avant.
new_list = list(my_list) # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]
pour prendre votre liste copiez une étape plus loin, copiez chaque objet auquel votre liste se réfère, et liez ces copies d'éléments à une nouvelle liste.
import copy
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]
ce n'est pas encore une copie profonde, parce que chaque élément d'une liste peut se référer à d'autres objets, tout comme la liste est liée à ses éléments. Pour recursivement copier chaque élément de la liste, puis chaque autre objet auquel se réfère chaque élément, et ainsi de suite: effectuer une copie profonde.
import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)
Voir la documentation pour plus d'informations sur les cas de coin dans la copie.
utiliser thing[:]
>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>>
Python est un langage pour le faire, c'est newList = oldList[:]
tous les autres contributeurs ont donné grand réponses, qui fonctionnent lorsque vous avez une liste de dimension unique (nivelé), cependant des méthodes mentionnées jusqu'à présent, seulement copy.deepcopy()
fonctionne pour cloner/copier une liste et ne pas l'avoir pointer vers les objets imbriqués list
lorsque vous travaillez avec multidimensionnels, imbriqués listes (liste de listes). Alors que Felix Kling s'y réfère dans sa réponse, Il ya un peu plus à la question et peut-être une solution de contournement en utilisant des built-ins qui pourrait s'avérer une alternative plus rapide à deepcopy
.
alors que new_list = old_list[:]
, copy.copy(old_list)'
et pour Py3k old_list.copy()
travaillent pour des listes à un seul niveau, ils reviennent à pointer vers les objets list
emboîtés dans le old_list
et le new_list
, et les changements à l'un des objets list
sont perpétués dans l'autre.
Edit: de Nouvelles informations portées à la lumière de
comme a été souligné par les deux Aaron Hall et PM 2Ring utiliser
eval()
n'est pas seulement une mauvaise idée, il est aussi beaucoup plus lent quecopy.deepcopy()
.cela signifie que pour les listes multidimensionnelles, la seule option est
copy.deepcopy()
. Cela étant dit, ce n'est vraiment pas une option car la performance va bien au sud quand vous essayez de l'utiliser sur un tableau multidimensionnel de taille moyenne. J'ai essayé detimeit
en utilisant un tableau 42x42, pas inconnu ou même aussi grand pour les applications bioinformatiques, et j'ai renoncé à attendre une réponse et j'ai juste commencé à taper mon édition à ce post.il semblerait que la seule vraie option soit alors d'initialiser plusieurs listes et de travailler sur elles indépendamment. Si quelqu'un a d'autres suggestions, pour savoir comment gérer la copie multidimensionnelle de listes, il serait apprécié.
Comme d'autres l'ont déclaré, Il peut être sont importantes problèmes de performance à l'aide du module copy
et copy.deepcopy
pour les listes multidimensionnelles . essayer de trouver une autre façon de copier la liste multidimensionnelle sans utiliser deepcopy
, (je travaillais sur un problème pour un cours qui ne permet que 5 secondes pour l'ensemble de l'algorithme pour exécuter afin de recevoir un crédit), j'ai trouvé un moyen d'utiliser les fonctions intégrées de faire une copie de la liste imbriquée sans les avoir point à un autre ou à l' list
objets imbriqués à l'intérieur d'eux. J'ai utilisé eval()
et repr()
dans l'attribution à faire de la copie de l'ancienne liste dans la nouvelle liste sans la création d'un lien avec l'ancienne liste. Il prend la forme de:
new_list = eval(repr(old_list))
essentiellement ce que cela fait est de faire une représentation de old_list
comme une chaîne, puis évalue la chaîne, comme si elle était l'objet de la chaîne représente. Ce faisant, aucun lien vers l'original list
objet. Un nouvel objet list
est créé et chaque variable pointe vers son propre objet indépendant. Voici un exemple utilisant une liste imbriquée en 2 dimensions.
old_list = [[0 for j in range(y)] for i in range(x)] # initialize (x,y) nested list
# assign a copy of old_list to new list without them pointing to the same list object
new_list = eval(repr(old_list))
# make a change to new_list
for j in range(y):
for i in range(x):
new_list[i][j] += 1
si vous vérifiez ensuite le contenu de chaque liste, par exemple une liste de 4 par 3, Python retournera
>>> new_list
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]
>>> old_list
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
bien que ce ne soit probablement pas la façon canonique ou syntaxique correcte de le faire, il semble bien fonctionner. Je n'ai pas testé la performance, mais je vais deviner que eval()
et rep()
auront moins de temps pour courir que deepcopy
.
contrairement à d'autres langues qui ont variable et valeur , Python a nom et objet .
Cette déclaration:
a = [1,2,3]
signifie donner à la liste (objet) un nom a
, et, ceci:
b = a
donne juste le même objet a
un nouveau nom b
, donc chaque fois que vous faites quelque chose avec a
, l'objet change et donc b
change.
La seule façon de faire un vraiment copie d'un est de créer un nouvel objet comme d'autres réponses ont déjà dit.
vous pouvez en savoir plus sur ce ici .
Python 3.6.0 Timings
Voici les résultats de synchronisation en utilisant Python 3.6.0. Gardez à l'esprit que ces temps sont relatifs les uns aux autres, pas absolus.
j'ai continué à ne faire que des copies superficielles, et j'ai aussi ajouté quelques nouvelles méthodes qui n'étaient pas possibles en Python2, comme list.copy()
(L'équivalent python3 slice ) et liste de déballage ( *new_list, = list
):
METHOD TIME TAKEN
b = a[:] 6.468942025996512 #Python2 winner
b = a.copy() 6.986593422974693 #Python3 "slice equivalent"
b = []; b.extend(a) 7.309216841997113
b = a[0:len(a)] 10.916740721993847
*b, = a 11.046738261007704
b = list(a) 11.761539687984623
b = [i for i in a] 24.66165203397395
b = copy.copy(a) 30.853400873980718
b = []
for item in a:
b.append(item) 48.19176080400939
nous peut voir le vieux gagnant sort toujours sur le dessus, mais pas vraiment par une quantité énorme, compte tenu de la lisibilité accrue de L'approche Python3 list.copy()
.
notez que ces méthodes font et non résultats équivalents de sortie pour toute entrée autre que les listes. ils travaillent tous pour des objets tranchables, quelques-uns travaillent pour n'importe quel itérable, mais seulement copy.copy()
fonctionne pour n'importe quel objet Python.
voici le code d'essai pour les parties intéressées ( modèle d'ici ):
import timeit
COUNT = 50000000
print("Array duplicating. Tests run", COUNT, "times")
setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy'
print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT))
print("b = copy.copy(a)\t\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT))
print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT))
print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT))
print("b = a[0:len(a)]\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT))
print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT))
print("b = []\nfor item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a: b.append(item)', setup=setup, number=COUNT))
print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT))
commençons par le début et explorons-le un peu profondément:
supposons donc que vous ayez deux listes:
list_1=['01','98']
list_2=[['01','98']]
et nous devons copier les deux listes, maintenant à partir de la première liste:
donc d'abord essayons par méthode générale de la copie:
copy=list_1
maintenant si vous pensez copier copié la list_1 alors vous pouvez vous tromper, vérifions:
The id() function shows us that both variables point to the same list object, i.e. they share this object.
print(id(copy))
print(id(list_1))
sortie:
4329485320
4329485320
surpris ? OK allons l'explorer:
comme nous le savons, python ne stocke rien dans une variable, les Variables font simplement référence à l'objet et l'objet stocke la valeur. Ici objet est list
mais nous avons créé deux références à ce même objet par deux noms de variables différentes. Donc les deux variables pointent vers le même objet :
ainsi quand vous faites copy=list_1
ce qu'il fait réellement:
ici dans l'image list_1 et copy sont deux noms de variables mais l'objet est le même pour les deux variables qui est list
donc si vous essayez de modifier la liste copiée alors il va modifier la liste originale aussi parce que la liste est un seul là, vous allez modifier cette liste non matière que vous faites à partir de la liste copiée ou de la liste originale:
copy[0]="modify"
print(copy)
print(list_1)
sortie:
['modify', '98']
['modify', '98']
de sorte qu'il a modifié la liste originale:
Quelle est la solution alors?
Solution:
passons maintenant à une deuxième méthode pythonique de liste de copie:
copy_1=list_1[:]
maintenant cette méthode fixer la chose ce que nous
print(id(copy_1))
print(id(list_1))
4338792136
4338791432
donc, comme nous pouvons voir que nos deux listes ont des id différents et cela signifie que les deux variables pointent vers des objets différents donc ce qui se passe réellement ici est:
essayons maintenant de modifier la liste et voyons si nous sommes toujours confrontés au problème précédent:
copy_1[0]="modify"
print(list_1)
print(copy_1)
sortie:
['01', '98']
['modify', '98']
comme vous pouvez le voir, il ne modifie pas la liste originale, il a seulement modifié la liste copiée, donc nous sommes ok avec elle.
donc maintenant je pense que nous avons fini? attendez, nous devons aussi copier la deuxième liste imbriquée, alors essayons pythonic way:
copy_2=list_2[:]
donc list_2 devrait faire référence à un autre objet qui est une copie de list_2 vérifions:
print(id((list_2)),id(copy_2))
nous obtenons la sortie:
4330403592 4330403528
maintenant nous pouvons supposer que les deux listes pointent un objet différent alors essayons de le modifier et voyons s'il donne ce que nous voulons:
ainsi quand nous essayons:
copy_2[0][1]="modify"
print(list_2,copy_2)
il nous donne de sortie:
[['01', 'modify']] [['01', 'modify']]
maintenant, c'est peu de confusion nous avons utilisé la manière pythonique et encore, nous sommes confrontés au même problème.
nous allons comprendre:
donc quand nous faisons:
copy_2=list_2[:]
nous sommes en train de copier la liste extérieure seulement, pas la liste imbriquée, donc la liste imbriquée est le même objet pour les deux listes, vérifions:
print(id(copy_2[0]))
print(id(list_2[0]))
sortie:
4329485832
4329485832
donc en fait quand nous faisons copy_2=list_2[:]
c'est ce qui se passe:
il crée la copie de la liste mais seulement l'extérieur la copie de liste, pas la copie de liste imbriquée, la liste imbriquée est la même pour les deux variables donc si vous essayez de modifier la liste imbriquée, alors elle modifiera la liste originale aussi parce que l'objet liste imbriquée est le même pour les deux listes imbriquées.
Quelle est donc la solution?
la Solution est deep copy
from copy import deepcopy
deep=deepcopy(list_2)
alors maintenant vérifions:
print(id((list_2)),id(deep))
sortie:
4322146056 4322148040
les deux id sont différents , maintenant vérifions l'id de liste imbriqué:
print(id(deep[0]))
print(id(list_2[0]))
sortie:
4322145992
4322145800
comme vous pouvez le voir les deux id sont différents de sorte que nous pouvons supposer que les deux listes imbriquées pointent un objet différent maintenant.
ainsi quand vous faites deep=deepcopy(list_2)
ce qui se passe réellement:
donc les deux listes imbriquées pointent objet différent et ils ont maintenant une copie de la liste emboîtée.
essayons maintenant de modifier la liste imbriquée et voyons si elle a résolu le problème précédent ou pas:
donc si nous le faisons:
deep[0][1]="modify"
print(list_2,deep)
sortie:
[['01', '98']] [['01', 'modify']]
comme vous pouvez le voir il n'a pas modifié la liste imbriquée originale , il a seulement modifié la liste copiée.
Si vous aimez ma réponse , laissez-moi savoir par upvoting il , si vous avez un doute realted cette réponse, commenter:)
cela me surprend que cela n'ait pas encore été mentionné, donc par souci d'exhaustivité...
vous pouvez effectuer le déballage de liste avec l '"opérateur splat": *
, qui va également copier des éléments de votre liste.
old_list = [1, 2, 3]
new_list = [*old_list]
new_list.append(4)
old_list == [1, 2, 3]
new_list == [1, 2, 3, 4]
l'inconvénient évident de cette méthode est qu'elle n'est disponible qu'en Python 3.5+.
Timing sage cependant, cela semble mieux fonctionner que d'autres méthodes communes.
x = [random.random() for _ in range(1000)]
%timeit a = list(x)
%timeit a = x.copy()
%timeit a = x[:]
%timeit a = [*x]
#: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Je ne sais pas si c'est encore le cas, mais le même comportement vaut pour les dictionnaires. Regardez cet exemple.
a = {'par' : [1,21,3], 'sar' : [5,6,8]}
b = a
c = a.copy()
a['har'] = [1,2,3]
a
Out[14]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]}
b
Out[15]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]}
c
Out[16]: {'par': [1, 21, 3], 'sar': [5, 6, 8]}
notez qu'il y a des cas où si vous avez défini votre propre classe personnalisée et que vous voulez conserver les attributs, vous devez utiliser copy.copy()
ou copy.deepcopy()
plutôt que les alternatives, par exemple en Python 3:
import copy
class MyList(list):
pass
lst = MyList([1,2,3])
lst.name = 'custom list'
d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}
for k,v in d.items():
print('lst: {}'.format(k), end=', ')
try:
name = v.name
except AttributeError:
name = 'NA'
print('name: {}'.format(name))
sorties:
lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list
new_list = my_list[:]
new_list = my_list
Essayer de comprendre cela. Disons que my_list est dans la mémoire tas à l'emplacement X, c'est-à-dire que my_list pointe vers le X. maintenant, en assignant new_list = my_list
, vous permettez à new_list de pointer vers le X. c'est ce qu'on appelle une copie superficielle.
maintenant si vous assignez new_list = my_list[:]
vous copiez simplement chaque objet de my_list à new_list. Ceci est connu en tant que copie en Profondeur.
L'autre façon que vous pouvez faire ceci sont:
-
new_list = list(old_list)
-
import copy new_list = copy.deepcopy(old_list)
une approche très simple indépendante de la version python manquait dans les réponses déjà données que vous pouvez utiliser la plupart du temps (au moins je le fais):
new_list = my_list * 1 #Solution 1 when you are not using nested lists
cependant, si my_list contient d'autres conteneurs (par exemple: listes imbriquées) vous devez utiliser deepcopy comme les autres suggérés dans les réponses ci-dessus de la bibliothèque de copie. Par exemple:
import copy
new_list = copy.deepcopy(my_list) #Solution 2 when you are using nested lists
. Bonus : si vous ne voulez pas copier d'éléments utiliser (alias shallow copie):
new_list = my_list[:]
comprenons la différence entre la Solution n ° 1 et la Solution n ° 2
>>> 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 la Solution n ° 1 a fonctionné parfaitement lorsque nous n'utilisions pas les listes imbriquées. Vérifions ce qui se passera lorsque nous appliquerons la solution n ° 1 aux listes imbriquées.
>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]] #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] #Solution #2 - DeepCopy worked in nested list
vous pouvez utiliser bulit dans la fonction list ():
newlist=list(oldlist)
je pense que ce code vous aidera.