Domanda

Di tanto in tanto vedo la sintassi della slice dell'elenco utilizzata nel codice Python in questo modo:

newList = oldList[:]

Sicuramente è lo stesso di:

newList = oldList

O mi sto perdendo qualcosa?

È stato utile?

Soluzione

Come ha detto NXC, i nomi delle variabili Python puntano effettivamente a un oggetto e non a un punto specifico nella memoria.

newList = oldList creerebbe due diverse variabili che puntano allo stesso oggetto, pertanto, cambiando oldList cambierebbe anche newList .

Tuttavia, quando si esegue newList = oldList [:] , esso " sezioni " l'elenco e crea un nuovo elenco. I valori predefiniti per [:] sono 0 e la fine dell'elenco, quindi copia tutto. Pertanto, crea un nuovo elenco con tutti i dati contenuti nel primo, ma entrambi possono essere modificati senza cambiare l'altro.

Altri suggerimenti

[:] Copie superficiali l'elenco, facendo una copia della struttura dell'elenco contenente riferimenti ai membri dell'elenco originale. Ciò significa che le operazioni sulla copia non influiscono sulla struttura dell'originale. Tuttavia, se fai qualcosa ai membri dell'elenco, entrambi gli elenchi fanno ancora riferimento a loro, quindi gli aggiornamenti verranno visualizzati se si accede ai membri attraverso l'originale.

Una Deep Copy farebbe anche copie di tutti i membri della lista.

Lo snippet di codice seguente mostra una copia superficiale in azione.

# ================================================================
# === 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'esecuzione in una shell Python fornisce la seguente trascrizione. Possiamo vedere il lista fatta con copie dei vecchi oggetti. Uno degli oggetti può avere il suo stato viene aggiornato mediante riferimento attraverso l'elenco precedente e gli aggiornamenti possono essere visto quando si accede all'oggetto tramite il vecchio elenco. Infine, cambiando a si può vedere che il riferimento nel nuovo elenco non si riflette nel vecchio elenco, come il nuovo elenco si riferisce ora a un oggetto diverso.

>>> # ================================================================
... # === 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

Come è già stato risposto, aggiungerò semplicemente una semplice dimostrazione:

>>> 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]

Non pensare mai che 'a = b' in Python significhi 'copia b in a'. Se ci sono variabili su entrambi i lati, non puoi davvero saperlo. Invece, pensalo come 'dai a b il nome aggiuntivo a'.

Se b è un oggetto immutabile (come un numero, tupla o una stringa), allora sì, l'effetto è che ottieni una copia. Ma questo perché quando hai a che fare con immutabili (che forse avrebbero dovuto essere chiamati sola lettura , immutabile o WORM ) sempre ottieni una copia, per definizione.

Se b è modificabile, devi sempre fare qualcosa in più per essere sicuro di avere una copia vera . sempre . Con le liste, è semplice come una sezione: & nbsp; a = b [:].

La mutabilità è anche la ragione per cui:

def myfunction(mylist=[]): 
    pass

... non fa proprio quello che pensi che faccia.

Se vieni da uno sfondo C: ciò che rimane di '=' è sempre un puntatore. Tutte le variabili sono puntatori, sempre. Se inserisci le variabili in un elenco: & nbsp; a = [b, c], hai inserito i puntatori ai valori indicati da b e c in un elenco indicato da a. Se si imposta quindi [0] = d, il puntatore in posizione 0 ora punta a qualunque punto d.

Vedi anche il modulo di copia: & nbsp; http://docs.python.org/ biblioteca / copy.html

Copia superficiale: (copia blocchi di memoria da una posizione all'altra)

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']

Deep Copy: (copia il riferimento all'oggetto)

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']
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top