0

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?

martineau
  • 119,623
  • 25
  • 170
  • 301
Mahin
  • 449
  • 2
  • 14
  • 25
  • 1
    You need to copy the list to create a new list. If `x` is a list and you write `y = x`, y and x will be the same list. To make y be a copy of x, `y = x.copy()` or `y = x[:]`, – Frank Yellin Sep 28 '21 at 17:44
  • In your original code simply doing `lastRow = output[i - 1][:]` should be enough to fix the issue. – rdas Sep 28 '21 at 17:46
  • **Python never uses pass by reference**. This has *nothing to do with pass by reference* – juanpa.arrivillaga Sep 28 '21 at 17:53
  • "Even if you create a third variable with completely independent on the stack, " *there is no stack*. What are you talking about? Variables are *just names that refer to objects*. When you do `x = y` that doesn't *create a new object that has the same value as `y`*, that creates a *new name* to refer to the *same object*. – juanpa.arrivillaga Sep 28 '21 at 17:55
  • 1
    You need to *copy the object*. That's the problem. In this case, you probably just need `lastRow = output[i - 1].copy()` – juanpa.arrivillaga Sep 28 '21 at 17:56

0 Answers0