Pergunta

Eu ocasionalmente ver a sintaxe lista fatia usado no código Python como esta:

newList = oldList[:]

Com certeza este é apenas o mesmo que:

newList = oldList

Ou estou faltando alguma coisa?

Foi útil?

Solução

Como NXC disse, nomes de variáveis ??em Python que apontam para um objeto, e não um ponto específico na memória.

newList = oldList criaria duas variáveis ??diferentes que apontam para o mesmo objeto, portanto, mudando oldList também mudaria newList.

No entanto, quando você faz newList = oldList[:], ele "fatias" da lista, e cria uma nova lista. Os valores padrão para [:] são 0 e o fim da lista, então ele copia tudo. Portanto, ele cria uma nova lista com todos os dados contidos no primeiro, mas ambos podem ser alterados sem alterar o outro.

Outras dicas

[:] href="http://en.wikipedia.org/wiki/Deep_copy#Shallow_copy" rel="noreferrer"> cópias rasas a lista, fazendo uma cópia da estrutura de lista contendo referências a a lista de membros originais. Isto significa que as operações na cópia não afetam a estrutura do original. No entanto, se você fizer algo para os membros da lista, ambas as listas ainda se referem a eles, para que as atualizações aparecerão se os membros são acessados ??através do original.

A profunda Copiar iria fazer cópias de todos os membros da lista também.

O trecho de código a seguir mostra uma cópia superficial em ação.

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

Executá-lo em um shell python dá a seguinte transcrição. Podemos ver o lista que está sendo feito com cópias dos objetos antigos. Um dos objetos podem ter seu estado atualizado por referência através da lista de idade, e as atualizações podem ser visto quando o objeto é acessado através da lista de idade. Finalmente, a mudança de uma referência na nova lista pode ser visto a não refletir na lista velha, como o nova lista está agora referindo-se a um objeto diferente.

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

Como já foi respondida, eu vou simplesmente adicionar uma demonstração simples:

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

Nunca pense que 'a = b' em Python significa 'cópia de b para a'. Se houver variáveis ??de ambos os lados, você realmente não pode saber disso. Em vez disso, pense nisso como 'give b o nome de um adicional'.

Se b é um objeto imutável (como um número, tupla ou uma string), então sim, o efeito é que você começa uma cópia. Mas isso é porque quando você lida com imutáveis ??(que talvez deveria ter sido chamado somente leitura , imutável ou WORM ) você sempre obter uma cópia, por definição.

Se b é um mutável, você sempre tem que fazer algo extra para ter certeza de ter uma cópia fiel . Sempre . Com listas, é tão simples como uma fatia: a = b [:].

A mutabilidade é também a razão que este:

def myfunction(mylist=[]): 
    pass

... não chega a fazer o que você acha que ele faz.

Se você é um C-fundo: o que resta do '=' é um ponteiro, sempre. Todas as variáveis ??são ponteiros, sempre. Se você colocar variáveis ??em uma lista: a = [b, c], você colocou ponteiros para os valores apontado por b e c em uma lista apontada por um. Se você seguida, defina a [0] = d, o ponteiro na posição 0 está agora apontando para o que quer que d aponta para.

Veja também a cópia do módulo: http://docs.python.org/library/ copy.html

rasa Copiar: (copia blocos de memória de um local para outro)

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 Cópia: (cópias de objetos de referência)

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']
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top