2

I am trying to understand why the first for loop does not return what the second for loop is returning. Can anyone explain this clearly to me? My searching did not unearth any results since I don't know what this problem is called.

arr = [1,2,3]
tempArr = []
res = []

for num in range(0,3):
  tempArr.append(arr[num])
  res.append(tempArr)
  print(tempArr, res)

print()

tempArr = []
res = []
for num in range(0,3):
  tempArr.append(arr[num])
  res.append(list(tempArr))
  print(tempArr, res)

Returns:

[1] [[1]]
[1, 2] [[1, 2], [1, 2]]
[1, 2, 3] [[1, 2, 3], [1, 2, 3], [1, 2, 3]]

[1] [[1]]
[1, 2] [[1], [1, 2]]
[1, 2, 3] [[1], [1, 2], [1, 2, 3]]
1
  • res.append(tempArr) appends a reference to the mutable object tempArr. res.append(list(tempArr)) appends a static copy of it. Commented Jun 11, 2022 at 13:24

3 Answers 3

2

Lists in Python are mutable sequences. This means that you can modify the elements of a list once it is created.

You are creating a list and assigning it to the variable 'tempArr'. Then in the first loop you are appending 'tempArr' to the 'res' list. Note that because lists are mutable, you are never changing what 'tempArr' is, you only modify its content, so you are adding three times the same list to 'res'. When you modify the 'tempArr' list, you modify all the lists inside 'res' (again, because they are the same list)

An explicit example you can play with is the following:

# Create a new list
tempArr = []
# Create a list containing the initial one (which is empty)
res = [tempArr]
# Now, lets modify the 'tempArr'
tempArr.append("This wasn't here before")
# Make your prediction on what will happen now:
print(res)

Another thing we can do is play with the 'is' comparison, in your code:

arr = [1,2,3]
tempArr = []
res = []
for num in range(0,3):
    tempArr.append(arr[num])
    res.append(tempArr)
    # Check if the element we have appended into 'res' is the 'tempArr' list. The result is always True.
    print(tempArr is res[-1])
    print(tempArr, res)
# Let's compare the three elements of the 'res' list and check if they are the same list, we see that they are.
print(res[0] is res[1] is res[2])

On the other hand, in the second loop, you are not appending the 'tempArr' list into 'res', you are first creating a new list by calling "list(tempArr)", and then appending this new list into 'res'. Now we can play a little bit with this:

tempArr = []
res = []
for num in range(0,3):
    tempArr.append(arr[num])
    res.append(list(tempArr))
    # Check if the element we have appended into 'res' is the 'tempArr' list.
    print(tempArr is res[-1])
    # This time the result is False. So we are not appending 'tempArr', but a new list with the same elements.
    print(tempArr, res)
# Let's compare again the three elements of the 'res' list and see if they are the same elements:
print(res[0] is res[1] is res[2])

As a consequence, because in the second loop we are creating new lists, when you modify the initial one, this doesn't affect the elements inside the 'res' list.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect answer, this has helped me so much!
2

list(...) makes a copy. Without making a copy, the same reference is appended, thus subsequent changes show up later in earlier elements as well.

To see the references, do a print(list(map(id, res))). If the printed number is the same, then it's the same list object.

Comments

1

Because we use list() to make shallow copy

This means list(tempArr) will now be a new and independent object with the same contents as tempArr

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.