Question

Je vois parfois la syntaxe de la liste slice utilisée dans le code Python comme ceci:

newList = oldList[:]

C’est sûrement la même chose que:

newList = oldList

Ou est-ce que je manque quelque chose?

Était-ce utile?

La solution

Comme NXC l’a dit, les noms de variables Python pointent en fait sur un objet et non sur un emplacement spécifique en mémoire.

newList = oldList créerait deux variables différentes qui pointent vers le même objet. Par conséquent, changer oldList modifierait également newList .

Cependant, lorsque vous faites newList = oldList [:] , il "slices". la liste et crée une nouvelle liste. Les valeurs par défaut pour [:] sont 0 et la fin de la liste, ainsi tout est copié. Par conséquent, il crée une nouvelle liste avec toutes les données contenues dans la première, mais les deux peuvent être modifiés sans modifier l'autre.

Autres conseils

[:] la copie superficielle de la liste en faisant une copie de la structure de liste contenant les références aux membres de la liste d'origine. Cela signifie que les opérations sur la copie n'affectent pas la structure de l'original. Cependant, si vous faites quelque chose aux membres de la liste, les deux listes s'y réfèrent toujours, ainsi les mises à jour s'afficheront si les membres sont accessibles via l'original.

Une Copie profonde copie également tous les membres de la liste.

L'extrait de code ci-dessous montre une copie superficielle en action.

# ================================================================
# === ShallowCopy.py =============================================
# ================================================================
#
class Foo:
    def __init__(self, data):
        self._data = data

aa = Foo ('aaa')
bb = Foo ('bbb')

# The initial list has two elements containing 'aaa' and 'bbb'
OldList = [aa,bb]
print OldList[0]._data

# The shallow copy makes a new list pointing to the old elements
NewList = OldList[:]
print NewList[0]._data

# Updating one of the elements through the new list sees the
# change reflected when you access that element through the
# old list.
NewList[0]._data = 'xxx'
print OldList[0]._data

# Updating the new list to point to something new is not reflected
# in the old list.
NewList[0] = Foo ('ccc')
print NewList[0]._data
print OldList[0]._data

L'exécuter dans un shell python donne la transcription suivante. On peut voir le liste étant faite avec des copies des anciens objets. Un des objets peut avoir son état est mis à jour par référence dans l'ancienne liste, et les mises à jour peuvent être visible lors de l'accès à l'objet via l'ancienne liste. Enfin, changer un référence dans la nouvelle liste peut être considérée comme ne reflétant pas dans l'ancienne liste, la nouvelle liste fait maintenant référence à un autre objet.

>>> # ================================================================
... # === ShallowCopy.py =============================================
... # ================================================================
... #
... class Foo:
...     def __init__(self, data):
...         self._data = data
...
>>> aa = Foo ('aaa')
>>> bb = Foo ('bbb')
>>>
>>> # The initial list has two elements containing 'aaa' and 'bbb'
... OldList = [aa,bb]
>>> print OldList[0]._data
aaa
>>>
>>> # The shallow copy makes a new list pointing to the old elements
... NewList = OldList[:]
>>> print NewList[0]._data
aaa
>>>
>>> # Updating one of the elements through the new list sees the
... # change reflected when you access that element through the
... # old list.
... NewList[0]._data = 'xxx'
>>> print OldList[0]._data
xxx
>>>
>>> # Updating the new list to point to something new is not reflected
... # in the old list.
... NewList[0] = Foo ('ccc')
>>> print NewList[0]._data
ccc
>>> print OldList[0]._data
xxx

Comme cela a déjà été répondu, je vais simplement ajouter une démonstration simple:

>>> a = [1, 2, 3, 4]
>>> b = a
>>> c = a[:]
>>> b[2] = 10
>>> c[3] = 20
>>> a
[1, 2, 10, 4]
>>> b
[1, 2, 10, 4]
>>> c
[1, 2, 3, 20]

Ne pensez jamais que "a = b" en Python signifie "copier b en a". S'il y a des variables des deux côtés, vous ne pouvez pas vraiment le savoir. Pensez-y plutôt comme "donnez à b le nom supplémentaire un".

Si b est un objet immuable (comme un nombre, un tuple ou une chaîne), alors oui, vous obtenez une copie. Mais c’est parce que lorsque vous traitez avec des immuables (que l’on aurait peut-être dû appeler en lecture seule , non modifiables ou WORM ), vous toujours obtenir une copie, par définition.

Si b est un mutable, vous devez toujours faire quelque chose de plus pour être sûr d'avoir une copie conforme . Toujours . Avec les listes, c’est aussi simple qu’une tranche: & nbsp; a = b [:].

La mutabilité est aussi la raison pour laquelle:

def myfunction(mylist=[]): 
    pass

... ne fait pas tout à fait ce que vous pensez qu'il fait.

Si vous êtes issu d'un C-background: ce qui reste du '=' est un pointeur, toujours. Toutes les variables sont des pointeurs, toujours. Si vous mettez des variables dans une liste: & nbsp; a = [b, c], vous avez mis des pointeurs sur les valeurs pointées par b et c dans une liste pointée par a. Si vous définissez ensuite un [0] = d, le pointeur en position 0 pointe maintenant sur le point d indiqué.

Voir aussi le module de copie: & nbsp; http://docs.python.org/ bibliothèque / copie.html

Copie peu profonde: (copie des morceaux de mémoire d'un emplacement à un autre)

a = ['one','two','three']

b = a[:]

b[1] = 2

print id(a), a #Output: 1077248300 ['one', 'two', 'three']
print id(b), b #Output: 1077248908 ['one', 2, 'three']

Copie profonde: (Copie de référence d'objet)

a = ['one','two','three']

b = a

b[1] = 2


print id(a), a #Output: 1077248300 ['one', 2, 'three']
print id(b), b #Output: 1077248300 ['one', 2, 'three']
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top