List value appears to change randomly

For some reason my list is updating index values randomly. The code simply runs through a list (mylist), with 2 numbers to reference each element, and a character to store at that element, in another list montharray. When I observe the value of random elements in montharray, eg. montharray[5][15]`, I notice the value changes several times, as I go through each iteration for the loop. I’m stuck.

for n in range(0, len(mylist), 3):
    print()
    montharray[int(mylist[n]) - 1][int(mylist[n + 1]) - 1] = mylist[n + 3]
            print(montharray[5][15])
print()
    

Mylist ['0', '1', 'J', '0', '2', 'A', '0', '2', 'S', '1', '3', 'N', '1', '7', 'D', '2', '3', 'M', '2', '3', 'S', '3', '4', 'F'…cont.

I’ve observed montharray[5][15] to see when it changes. It appears that it is assigned the same value of cell [0][15] when that is assigned through the loop, and than at every [n][15] value afterwards.

You didn’t specify what the end result should be nor how montharray is defined. I cannot say 100% what the issue is but I can make a pretty reasonable guess. The way you index mylist is not quite right. Doing some loop unrolling and tracing we can see something may not be right.

mylist =  ['0', '1', 'J', '0', '2', 'A', '0']

for n in range(0, len(mylist), 3) # [0, 3]
# Loop 0
n = 0
idx1 = int(mylist[n]) - 1   # == int(mylist[0]) - 1   == 0 - 1 == -1
idx2 = int(mylist[n+1]) - 1 # == int(mylist[0+1]) - 1 == 1 - 1 ==  0
idx3 = n + 3 # == 0 + 3 == 3
montharray[idx1][idx2] = mylist[idx3] # montharray[-1][0] = mylist[3] == ‘0’
# Loop 1
n = 3
idx1 = int(mylist[n]) - 1   # == int(mylist[3]) - 1   == 0 - 1 == -1
idx2 = int(mylist[n+1]) - 1 # == int(mylist[3+1]) - 1 == 2 - 1 ==  1
idx3 = n + 3 # == 3 + 3 == 6
montharray[idx1][idx2] = mylist[idx3] # montharray[-1][1] = mylist[6] == '0'

Since mylist is truncated and montharray is not provided I can’t observe montharray[5][15], but I’m willing to guess that the issue is the -1 indexes. When you trace your code you got -1 as the first index. In Python a -1 index means “the last index” and a -2 means “the index before the last” and so on.

If montharray has a length of 6 the last index would be 5. So montharray[-1] == montharray[5]. Basically, on your first iteration you’re assigning to the last index. If this is the expected behavior then you will need to provide a little more context for us to examine.

1 Like

So I changed the loop and removed all -1 indexing. The program still exhibits the same phenomena. In this case , as soon as [3][15] was assigned through the loop, [5][15] was also assigned the same value. This is very strange, but something must be happening between the two lists

You haven’t said how montharray is defined. Do multiple elements of montharrayrefer to the same list?

2 Likes

Montharray is just an empty list . Nothing else references montharray. The problem is evident from within the loop defining each value for montharray.

for n in range(0, len(mylist), 3):  

        print() 
       #Define the element value for each location in montharray
        montharray[int(mylist[n])][int(mylist[n + 1])] = mylist[n + 2]                 
       #These two lines always print correct corresponding Cell pair and corresponding character
        print(int(mylist[n]), int(mylist[n+1]))
        print(montharray[int(mylist[n])][int(mylist[n+1])]
       #This line below will reveal strange behaviour. As the loop starts it will simply print a blank space, but at some iteration, it will suddenly assign a value to the cell, *before* it is supposed to be defined in the loop
        print(montharray[5][15])

This happens to other cells too - somehow they are assigned values at seemingly random times, but I see nothing wrong with how I am implementing this.

If that were true you’d have an error as soon as you tried to index into it.

I suggest you just post the full script, without it we’re all just guessing at what you might have done.

Edit: but since I can’t resist guessing: it sounds like you assigned the same list to two variables and expected them to be Independent copies. But you’re actually modifying one list from multiple places.

Did you do something like montharray = [[]] * 12 ?

1 Like

Yes, in fact montharray is assigned (non-dynamically) as such:

    montharray = [[' ']  * xmax]  * ymax

Is that not just defining a single 2d dimensional array?

There’s your pain point. You aren’t creating a list of lists, you are creating an outer list that holds ymax references to the same inner list.

If you did print([object()]*10), you’d see that all of the <object at 0xXYZ> have exact same XYZ.

1 Like

Python uses references and doesn’t make copies unless you tell it to.

If a variable x refers to some object:

    x ──→ <object>

and you assign to y with y = x, then y will refer to that same object:

    x ─╮
       ├─→ <object>
    y ─╯

Similarly, if you have a list that contains some object, it actually contains a reference to it:

    [ _ ]
      │
      ↓
      <object>

and if you use * to repeat the list, it repeats the reference - it doesn’t copy the object itself:

    [  _ _ ]
       │ │
       ╰┬╯
        │
        ↓
        <object>

montharray contains ymax references to the same list.

Generally speaking, you would write something like this:

    montharray = [[make_object() for _ in range(xmax)] for _ in range(ymax)]

if the objects were mutable and you were going to mutate them.

However, you’re initialising when strings that you’re going to be replacing, so you can write:

    montharray = [[' '] * xmax for _ in range(ymax)]

That makes ymax separate lists for montharray.

3 Likes

Ah, so this is quite different than what I am used to in C++, where I feel arrays are a bit more intuitive overall. I made the correction and the code works. Thanks for the help!