3

I am using Python 3.4.
I noticed this curious behaviour:

In [1]: a=[1,2,3,4,5,6,7,8,9]
In [2]: b=[10,11,12,13,14,15,16,17,18,19]
In [3]: type(a)
Out[3]: list

In [4]: a
Out[4]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [5]: b
Out[5]: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

In [6]: c=a
In [7]: c
Out[7]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [8]: c.extend(b)

In [9]: c
Out[9]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

In [10]: a
Out[10]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Why is a modified by the extend method applied on c?
Do you observe the same behaviour?
Is it normal? And in this case, how can I extend c leaving a intact?

Pang
  • 9,564
  • 146
  • 81
  • 122
Romn
  • 174
  • 2
  • 14
  • This is a very common python question. Look up the difference between deep and shallow copying. – Loocid Jun 05 '15 at 03:04
  • 1
    On line `In [6]: c=a` you did not copy the list, you set `c` to reference the same list `a` is referencing. You can verify that by doing `id(a)` and `id(c)`. – Akavall Jun 05 '15 at 03:06
  • 1
    `c=a` means that `c` is a reference to the same list that `a` refers to. If you modify that list you will see that modification no matter what you call it. `list(a)` makes a copy of the list that `a` refers to. So if you write `c = list(a)`, then `c` and `a` will refer to *different* lists with identical contents (until you modify one of them). – Eric Appelt Jun 05 '15 at 03:07
  • Ok, I wasn't aware about that (never seen in it in any beginer tutorial for Python). Thank you for poiting this and sorry for useless question. – Romn Jun 05 '15 at 03:13
  • @Romn This is neither a useless nor trivial question. What you did was synonymous to, in the C programming language, when you assign a pointer `c` to the same memory address pointed to by `a`. I hate how puritanical a lot of Python developers are about saying, "Oh, but pointers don't exist in Python, so it's technically wrong. Truth is, using pointers as an analogy is a wonderful way to intuitively explain the concept to new people. Being technically correct doesn't always translate to being helpful. – Dave Liu Sep 12 '19 at 18:18

1 Answers1

3

Because you set c as a some lines before you assign c on line In [6].

Edit: Since my answer is not that deep have a look at that.

You want to make c as a new list by copying a. But there are two ways to copy: shallow and deep copy.

You want to have two seperate lists so you need deepcopy.
You cannot use list() since it will shallow copy your list and so both your lists will still be 'connected'. When you change one value it will be changed in the other list as well.
When you use

c = copy.deepcopy(a)

You will get two separate lists.

Tom-Oliver Heidel
  • 1,011
  • 9
  • 25
  • 1
    more specifically you need to copy the list by doing `c = list(a)` or `c = a[:]` you have to edit the original list otherwise it won't create a new entry in memory – Alexander McFarlane Jun 05 '15 at 03:20
  • You can make use of [:] when you have a simple list. But list() will just make a shallow copy. – Tom-Oliver Heidel Jun 05 '15 at 03:23
  • using `import copy` is a bit of a waste of effort in this case. [This post](http://stackoverflow.com/a/2612815/4013571) suggests it is slower as well – Alexander McFarlane Jun 05 '15 at 03:25
  • You have to do it if you want a new list which is not linked with the original one. Try it on your own if you use list() and make a change to the new list the old one will be changed as well. deepcopy is the only solution to this. – Tom-Oliver Heidel Jun 05 '15 at 03:37
  • @alexmcf deepcopy is slower (10ms; shallow copy just 1ms) but you will not notice anything because this is such little amount of time. And so on and so on. Sorry but I am tired of discussing on this. – Tom-Oliver Heidel Jun 05 '15 at 03:45