Python: Cópia "rasa" de listas

Palavras-chave: Python, listas, cópia, objetos

Em Python as variáveis não armazenam os objetos quando atribuímos um valor à elas. Ao invés disso uma variável em Python guarda apenas uma referência para o objeto em questão. Uma prova disto pode ser vista a seguir:

[python]
>>> a = [1,2,3]
>>> b = a
>>> b is a
True
>>> a.append(4)
>>> b
[1, 2, 3, 4]
[/python]

Por essa razão precisamos fazer cópias dos objetos quando queremos manipular os dados de uma das variáveis sem afetar os dados da outra.

A biblioteca Python disponibiliza o módulo copy para essa tarefa, mas em casos de listas (ou qualquer outra seqüência como strings e tuplas) existe uma maneira mais simples de se fazer isso: utilizando slicing, veja:

>>> a = [1,2,3]
>>> b = a[:]
>>> a is b
False
>>> a.append(4)
>>> b
[1, 2, 3]
>>> a
[1, 2, 3, 4]

A operação de slicing retornou uma cópia idêntica da lista porque a[:] é o mesmo que a[0:len(a)]. Vale lembrar, porém, que apenas a lista é copiada e não os objetos que estão dentro dela.

This entry was posted in Python. Bookmark the permalink.

6 Responses to Python: Cópia "rasa" de listas

  1. Vale lembrar que a necessidade de fazer uma cópia não é tão comum quanto parece.

    Outro ponto importante são os objetos imutáveis (como strings e números).

    Por exemplo:

    a = “Luciano”
    b = a

    a == b # True
    a is b # True

    a += ” Pacheco”
    a # => “Luciano Pacheco”
    b # => “Luciano”

    Isso ocorre por que ao fazer “a += ‘ Pacheco'” é criada uma nova string e atribuída à variável “a”. A string inicial que “estava” na variável “a” é ficou intocada e portanto a variável “b” continou com o seu valor.

  2. cezeiro says:

    Luciano,
    então nesse caso não utilizado referência como o Osvaldo disse em: “Ao invés disso uma variável em Python guarda apenas uma referência para o objeto em questão”, mas sim feito uma cópia do conteúdo da variavel “a” para o conteúdo de “b”.

    Agora confundiu mais ainda :D

  3. Na verdade, o que eu disse está correto e o que o Luciano disse também está correto. São não estamos falando das mesmas coisas :)

    Uma coisa é o conceito de mutabilidade de um objeto e outra é como nós referenciamos esse objeto.

    Os objetos strings são imutáveis (assim como tuplas, números e mais alguns outros) e quando a gente faz uma concatenação de strings o que ocorre internamente é que uma nova string será criada com o resultado da concatenação e ela será referenciada pela mesma variável.

    E o que acontecerá com a string antiga? Ela perde a referência da variável e, caso seja a última referência dela, ela será “coletada” pelo garbage colector. O mesmo ocorre com a string que foi usada para a concatenação.

  4. Walter Cruz says:

    Ocorre uma abdução coletiva dos codarianos? Saudades das dicas!

  5. Vinicius says:

    Opa, tudo bem?
    Me tire essa dúvida se possível!
    Se eu tenho a seguinte lista:
    >>>> a = [[1,2,3], [4,5,6]]
    >>>> b = a[:]
    >>>> b[0][0] = 7
    >>>> a
    >>>> [[7,2,3], [4,5,6]]
    >>>> b
    >>>> [[7,2,3], [4,5,6]]

    Não sei pq ta tratando como referencia, vc sabe o motivo??

    E o mais louco, se na minha primeira alteração em b, for da forma:
    >>>> b[0] = [7,2,3]
    Não tem problema nenhum!

    Se alguém estiver com esse problema, use
    >>>> import copy
    >>>> b = copy.deepcopy(a)

    Valeu!
    Até mais

  6. Rafael A. de Almeida says:

    Valeu, salvou meu dia :)

Comments are closed.