Sabemos que um mesmo objecto pode ter associado diferentes nomes. Quando os objectos são imutáveis isso não coloca problemas. No exemplo abaixo o objecto 'abc' tem associado três nomes diferentes. Se alteramos algum deles o que acontece é que é criado um novo objecto que fica associado ao nome do objecto antigo. Lembre-se: as cadeias de caracteres são imutáveis!
01.
>>> cadeia_1
=
'abc'
02.
>>> cadeia_2
=
'abc'
03.
>>> cadeia_3
=
cadeia_1
04.
>>> id(cadeia_1)
05.
4357502896
06.
>>> id(cadeia_2)
07.
4357502896
08.
>>> id(cadeia_3)
09.
4357502896
10.
>>> cadeia_2
=
cadeia_2
+
'd'
11.
>>> cadeia_3
=
cadeia_3
+
'3'
12.
>>> cadeia_2
13.
'abcd'
14.
>>> cadeia_3
15.
'abc3'
16.
>>> cadeia_1
17.
'abc'
18.
>>> id(cadeia_2)
19.
4361446864
20.
>>> id(cadeia_3)
21.
4361446720
22.
>>> id(cadeia_1)
23.
4357502896
Quando usamos objectos mutáveis o caso muda de figura.
01.
>>> lista_1
=
[
1
,
2
,
3
]
02.
>>> lista_2
=
[
1
,
2
,
3
]
03.
>>> lista_3
=
lista_2
04.
>>> lista_1
05.
[
1
,
2
,
3
]
06.
>>> lista_2
07.
[
1
,
2
,
3
]
08.
>>> lista_3
09.
[
1
,
2
,
3
]
10.
>>> id(lista_1)
11.
4515141032
12.
>>> id(lista_2)
13.
4515145344
14.
>>> id(lista_3)
15.
4515145344
16.
>>> lista_1[
1
]
=
'b'
17.
>>> lista_1
18.
[
1
,
'b'
,
3
]
19.
>>> lista_2
20.
[
1
,
2
,
3
]
21.
>>> lista_3
22.
[
1
,
2
,
3
]
23.
>>> lista_2[
1
]
=
'X'
24.
>>> lista_1
25.
[
1
,
'b'
,
3
]
26.
>>> lista_2
27.
[
1
,
'X'
,
3
]
28.
>>> lista_3
29.
[
1
,
'X'
,
3
]
30.
>>>
Para melhor entender o que acontece vejamos a figura seguinte:

Como se pode ver a lista_2 e a lista_3 partilham a memória, e é isso que faz com que as modificações que afectam uma também afectem a outra. Um modo de resolver o problema consiste em fazer uma cópia do objecto em vez de partilharem a memória.
01.
>>> lista_1
=
[
1
,
2
,
3
]
02.
>>> lista_2
=
[
1
,
2
,
3
]
03.
>>> lista_3
=
lista_2[:]
# <-- cópia!
04.
>>> id(lista_1)
05.
4515141536
06.
>>> id(lista_2)
07.
4515105464
08.
>>> id(lista_3)
09.
4515140816
10.
>>> lista_3[
1
]
=
'Y'
11.
>>> lista_3
12.
[
1
,
'Y'
,
3
]
13.
>>> lista_2
14.
[
1
,
2
,
3
]
15.
>>>
A figura abaixo ilustra a situação.

Parece que podemos ficar descansados com esta solução. Mas veja-se uma nova situação.
01.
>>> lista_2
=
[
1
,[
2
],
3
]
02.
>>> lista_3
=
lista_2[:]
# <-- cópia?
03.
>>> id(lista_2)
04.
4515346624
05.
>>> id(lista_3)
06.
4515144696
07.
>>> lista_3[
1
][
0
]
=
'Z'
08.
>>> lista_3
09.
[
1
, [
'Z'
],
3
]
10.
>>> lista_2
11.
[
1
, [
'Z'
],
3
]
# oops!
12.
>>>
O que terá acontecido? Para entender vamos recorrer uma vez mais ao nosso diagrama de ligação dos nomes aos objectos. Como fica situação antes da alteração?

E depois da alteração da lista_3?

O método indicado de cópia apenas faz uma cópia de superfície, isto é, uma cópia ao primeiro nível. A única solução efectiva para esta questão é recorrer à função deepcopy do módulo copy.
01.
>>>
import
copy
02.
>>> lista_2
=
[
1
,[
2
],
3
]
03.
>>> lista_3
=
copy.deepcopy(lista_2)
#<-- cópia profunda!
04.
>>> id(lista_2)
05.
4515145344
06.
>>> id(lista_3)
07.
4515140816
08.
>>> lista_3[
1
][
0
]
=
'K'
09.
>>> lista_3
10.
[
1
, [
'K'
],
3
]
11.
>>> lista_2
12.
[
1
, [
2
],
3
]
# <-- Sem problemas!
13.
>>>
Vejamos graficamente o que acontece.

Agora nada é partilhado, a não ser os objectos primitivos (imutáveis). Por isso ao alteramos a ligação (profunda) na lista_3 nada se altera na lista_2.
Sem comentários:
Enviar um comentário