chuoky
chuoky

Reputation: 23

Recursive function variable confusion

megaList = []
clmsArrow = [[3],[2,3,4],[1,3,5],[3],[3],[3],[3]]

def columnState(y,amnt):
    "-1 for all values in a list of lists"
    megaList.append(y)
    print(y)
    for i in range(len(y)):
        for j in range(len(y[i])):
            y[i][j] -= 1
            if y[i][j] == 0:
                y[i][j] = 5

    if amnt != 1:
        return columnState(y,amnt-1)

columnState(clmsArrow,5)
print('\n')
for x in megaList:
    print(x)

''Output''

[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[2], [1, 2, 3], [5, 2, 4], [2], [2], [2], [2]]
[[1], [5, 1, 2], [4, 1, 3], [1], [1], [1], [1]]
[[5], [4, 5, 1], [3, 5, 2], [5], [5], [5], [5]]
[[4], [3, 4, 5], [2, 4, 1], [4], [4], [4], [4]]


[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]

Why can't I write out to global variable (list) properly? All I get is the same first function input times five

As seen in the output inside function everything is alright, but when I try to add the same variable to a list outside the function something goes wrong

Upvotes: 1

Views: 64

Answers (1)

Dan
Dan

Reputation: 45752

This is because you keep adding references to y in your mega_list. And if you change y you also change all the references to y. For example:

a = [1, 2]
b = [a, a]
print(b)
a[0] = 99
print(b)

which prints

[[1, 2], [1, 2]]
[[99, 2], [99, 2]]

notice how b changed even though I only change a. This is because b contains references to a instead of copies.

To fix this in your code you can simply add this to start of your function

y = deepcopy(y)

you'll need to also add

from copy import deepcopy

the reason you need deepcopy instead of simply doing y[:] is because your y is ` nested list i.e. all the lists inside of it are also just references to other lists and those also need to be copied.

Finally, the reason you are getting back to your original value is because you made amnt equal 5 and your function does nothing if you run if 5 times because of

        if y[i][j] == 0:
            y[i][j] = 5

so they are changing, they're just landing up back where they started. If you run

columnState(clmsArrow, 4)

for example then you'll see the change i.e. you get

[[3], [2, 3, 4], [1, 3, 5], [3], [3], [3], [3]]
[[2], [1, 2, 3], [5, 2, 4], [2], [2], [2], [2]]
[[1], [5, 1, 2], [4, 1, 3], [1], [1], [1], [1]]
[[5], [4, 5, 1], [3, 5, 2], [5], [5], [5], [5]]

[[4], [3, 4, 5], [2, 4, 1], [4], [4], [4], [4]]
[[4], [3, 4, 5], [2, 4, 1], [4], [4], [4], [4]]
[[4], [3, 4, 5], [2, 4, 1], [4], [4], [4], [4]]
[[4], [3, 4, 5], [2, 4, 1], [4], [4], [4], [4]]

Upvotes: 1

Related Questions