1

I simplified my code to get the error I required.

one = ['x']
two = ['y']
final_data = []
for r in range(1, 3):
    print(final_data, r)
    if r == 2:
        one[0] = two[0]
        print(one)
    final_data.append(one)
    print(final_data)
print(final_data)

The final data in 2nd loop is not modified but the end result is coming [['y'], ['y']] even though I expect it to come as [['x'], ['y']]

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    This is just basic behavior for mutable objects like `list`s. If you haven't already, you should take time to read through https://nedbatchelder.com/text/names.html . It will help you avoid confusing problems in the future. The important bit here is `"Assignment never copies data."` which you are expecting it to with `final_data.append(one)`. – Axe319 Sep 14 '21 at 11:56
  • 1
    @Axe319 That's not assignment, though it works the same. `one` is effectively "assigned" to an index of `final_data`. – wjandrea Sep 14 '21 at 12:37

2 Answers2

2

In this line one[0] = two[0] you change the value in list one and in the end when you print final_data you get [['y'], ['y']] because in list one you have 'y'.

You need for each iteration to create a copy of one. To copy a list you can use [:]. Then after you do what you want with one, copy old_one to one.

...
old_one = one[:]
...
one = old_one[:]

Try this:

one = ['x']
two = ['y']
final_data = []
for r in range(1, 3):
    print(final_data, r)
    old_one = one[:]
    if r == 2:
        one[0] = two[0]
        print(one)
    final_data.append(one)
    one = old_one[:]
    print(final_data)
print(final_data)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
I'mahdi
  • 23,382
  • 5
  • 22
  • 30
  • Yes, but the ['x'] is already appended to final_data and the final_data is changed to [['x']] after 1st loop then in second loop the modified one which is ['y'] got appended to final_data so it should be [['x'], ['y']] – Srinivas Piccalo Sep 14 '21 at 11:34
  • @SrinivasPiccalo you append `one` to list not `x` and when you change `one` then `final_list` is changing. – I'mahdi Sep 14 '21 at 11:43
  • Ok. Kindly tell how to get desired result that is '`[['x'], ['y']]` in the above situation. – Srinivas Piccalo Sep 14 '21 at 12:03
  • @SrinivasPiccalo I'm kind ;), edited answer – I'mahdi Sep 14 '21 at 12:11
  • @SrinivasPiccalo welcome, always remember when you write `list1 = list2` both array have same address if you want prevent this you need use `list1 = list2[:]` or use `copy()`, for more detail if you like read this link : https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it – I'mahdi Sep 14 '21 at 12:23
0

In short:

final_data.append( one )

does not add the contents of list one but a reference to the list called one to final_data.

In C / C++ terminology, a "pointer" (or "reference") to list one is added such that by the time r==2:

final_data = [ <reference to `one`>, <reference to `one`> ]

So by modifying one[0] to be one[0] = two[0], the contents of one are changed and consequently final_data will see those changes too.

Possibly a simpler solution is to:

import copy

...
final_data.append( copy.deepcopy(one) )

copy.deepcopy() generates - as the name implies - a full copy of the object, such that now a reference to a new list will be added to final_data in stead of (yet another) reference to the list called one.

emvee
  • 4,371
  • 23
  • 23