I was solving a problem in leetcode using python and got into a pass-by-reference situation. After verifying the problem in my local environment, I found the situation is related to how python pass or reference values within variables.
The situation is, when you assign a list value from a list of lists to another variable and perform stack operation (pop) on that variable, it also performs the same operation on the primary list. Even if you create a third variable with completely independent on the stack, and assign the primary list to the third variable, the stack operation is also performed on the third variable.
To demonstrate more clearly see the following example:
class Solution:
def generate(self, numRows: int) -> List[List[int]]:
output = []
output.append([1])
for i in range(1,numRows):
lastRow = output[i - 1]
loop = len(lastRow)
first = 0
second = lastRow.pop(0)
temp = []
for x in range(loop):
temp.append(first + second)
if len(lastRow) > 1:
first = second
second = lastRow.pop(0)
elif len(lastRow) == 1:
first = second
second = lastRow.pop(0)
elif len(lastRow) == 0:
temp.append(second + 0)
break
output.append(temp)
In the above code segment, my output
variable is a list of lists and my lastRow
is a variable that taking values from output
and I am performing pop
operation on it. But the operation automatically performs pop
operation on the output
variable. If I print
the values, I get the following result for my output
variable:
[[], [1, 1]]
[[], [], [1, 2, 1]]
[[], [], [], [1, 3, 3, 1]]
[[], [], [], [], [1, 4, 6, 4, 1]]
To avoid this, I have tried to create another variable with the class scope and tried to make it independent of the stack in the following code:
class Solution:
final_output = []
def generate(self, numRows: int) -> List[List[int]]:
output = []
output.append([1])
self.final_output = [0]*numRows
self.final_output[0] = [1]
for i in range(1,numRows):
test = output[i - 1]
lastRow = test
loop = len(lastRow)
first = 0
second = lastRow.pop(0)
temp = []
for x in range(loop):
temp.append(first + second)
if len(lastRow) > 1:
first = second
second = lastRow.pop(0)
elif len(lastRow) == 1:
first = second
second = lastRow.pop(0)
elif len(lastRow) == 0:
temp.append(second + 0)
break
output.append(temp)
self.final_output[i] = temp
print(self.final_output)
In the above code, two additional variables are added to make the variables more independent of each other: the final_output
variable and the test
variable, but it does not avoid the situation. New output is:
[[1], [1, 1], 0, 0, 0]
[[1], [], [1, 2, 1], 0, 0]
[[1], [], [], [1, 3, 3, 1], 0]
[[1], [], [], [], [1, 4, 6, 4, 1]]
I am assuming this is done to optimize memory usage. But can anybody suggest to me how I can avoid these kinds of situations, when I need to make operations made on a variable totally independent from the other variable?