Adding list elements during a Python loop always returns the same value

Asked

Viewed 1,086 times

1

I have the following code:

current = [0, 1]
someList = []

while True:
  for n in range(0, 2):
    current[n] += 1

  print(current) # [1,2] and [2,3]
  someList.append(current)

  if current == [2, 3]:
    break

print(someList) # [[2,3], [2,3]]

At each loop the variable current receives +1 for each item, when the current reaches the value [2,3] the loop stop. The supposed to be the someList have a value of [[1,2], [2,3]] but always ends with the ultimate value of current, that is, ended with [[2,3], [2,3]]. Why does this happen?

2 answers

5

A list is a type with semantics by reference and not by value, which you are adding to someList with the append() is a reference to current. The reference of current does not change at any time so the two times that adds something is adding the same value. When you print it, it takes the value that is being referenced at that moment, and it is [2, 3] so it appears twice. There is no longer the previous value in current, after you changed the value of it the old no longer exists, as any variable since there is a value.

So to solve you need to have different references by cloning the list by creating another separate list that has no other reference to it that can affect its value (This may have undesirable effects in certain situations or make the code inefficient in heavier scenarios, so you can’t use it naively, you need to understand the memory model well). Something like this (has other forms) solves:

current = [0, 1]
someList = []
while True:
    for n in range(0, 2):
        current[n] += 1
    print(current)
    someList.append(current[:])
    if current == [2, 3]:
        break
print(someList)

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

It would be nice to understand What is a variable?. In Python it has some extra complication but that’s it.

5


This is because while doing append(current) you are not adding a new object to the list but the reference of the same object.

When you create a list and assign it to a variable, what you assigned was the memory address for the created object. To prove this, we can do this test:

lista1 = [1,2,3]
lista2 = lista1
lista2.clear()
print(lista1) # Saída: []

And how then to generate a copy of the object ?

We can use the method copy(). This method will create and return a new object with the same data as the original object. So, your corrected code looks like this:

current = [0, 1]
someList = []

while True:
  for n in range(0, 2):
    current[n] += 1

  print(current) # [1,2] and [2,3]
  someList.append(current.copy())

  if current == [2, 3]:
    break

print(someList) # [[1,3], [2,3]]

If you still don’t understand very well about all that I said, how about researching a little for "reference variables" ? Here website you may know a little more about this subject.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.