0

I am trying to append small (num) lists to a final list (lst). The small lists are modified in a loop and at each modification they are appended to the final list. But the result is strange and I did not like the solution. Here is the code.

n   = 3
num = []
lst = []

for i in range(n) :
    num.append(0)

lst.append(num)

for j in range(n-1) :
    for i in range(n) :
        num[i] += 1
        lst.append(num)

for each in lst :
    print each

The result of this code is:

[2, 2, 2]
[2, 2, 2]
[2, 2, 2]
[2, 2, 2]
[2, 2, 2]
[2, 2, 2]
[2, 2, 2]

However, if instead of using lst.append(num), I use lst.append(list(num)), I get the expected result:

[0, 0, 0]
[1, 0, 0]
[1, 1, 0]
[1, 1, 1]
[2, 1, 1]
[2, 2, 1]
[2, 2, 2]

Is this really the correct way for appending values of a list to another list?

UPDATE: I see that when I do lst.append(num) this does not mean that the values of num are appended to lst. It is a reference and because I change the content of num, in the end, all entries of my list lst will reference to the final num. However, if I do this:

lst = []

for i in range(3) :
    num = i
    lst.append(num)

for each in lst :
    print each

I get what is expected, i.e., a list lst with the values [0, 1 , 2]. And in this case, num is changed at every iteration and its final value is num=2.

  • 2
    **Hint:** Try `[id(x) for x in lst]` – Ashwini Chaudhary Mar 10 '16 at 17:46
  • If you want to extend (modify-in-place) a list with another list, you can use `a.extend(b)` – Tom Dalton Mar 10 '16 at 17:47
  • The issue you're seeing is because you're putting a reference to `num` into `lst`, rather than *a copy of num as it looks right now*. When you do `lst.append(list(num))`, you're making a *copy* of `num` and putting that into `lst`, and that copy then doesn't change when you modify `num`. – Tom Dalton Mar 10 '16 at 17:50
  • Did not you notice the strange thing? For example, at line 8 I append 'num' to 'lst'. At this moment, the list 'num' is [0, 0, 0]. But at the end when I print, this value do not show up in the list 'lst'. UPDATE: @TomDalton that is what I was thinking. – Alexandre de Castro Maciel Mar 10 '16 at 17:52

2 Answers2

1

Lets have a closer look at this loop.

for i in range(n) :
     num[i] += 1
     lst.append(num)

You are appending same num multiple times. So, all elements of lst has the same reference to list num and you are updating it at each iteration. That is why you are getting same value at each element of lst after the loop has completed.

But, when you are doing lst.append(list(num)), you are generating a new list each time. So, each element of lst has different reference. And you are getting expected output.

So, to answer your question, the way you are adding a list to a list is fine. That is how you should do it. It has nothing to do with your expected outcome.

Hossain Muctadir
  • 3,546
  • 1
  • 19
  • 33
  • Ok. I understood. Thank you. But I now I have another question on top of that. If I later change completely the value of num and append to the list like: ` num = 'other thing' lst.append(num) ` Then the result is: ` [2, 2, 2] [2, 2, 2] [2, 2, 2] [2, 2, 2] [2, 2, 2] [2, 2, 2] [2, 2, 2] other thing ` – Alexandre de Castro Maciel Mar 10 '16 at 18:02
  • Also see "How do I copy an object in Python?" in the [Programming FAQ](https://docs.python.org/3/faq/programming.html). list(num) is not the nice way to copy a list. – mkiever Mar 10 '16 at 18:18
  • @mkiever I see now that is best use num[:] than list(num) to copy the values of num as list to another list – Alexandre de Castro Maciel Mar 10 '16 at 18:35
1

I think the explanation for your result is that when you do num[i] += 1 you are actually modifying the preceding copies of num that were appended in lst at previous stages of the loop. When you do lst.append(list(num)) you are creating a unique version of num.

Brian Huey
  • 1,550
  • 10
  • 14