Search code examples
pythonnumpypass-by-referenceside-effects

What is the difference? numpy.array pass by ref


Why do we have two different behaviors on these np.array?

    def pass_by_ref(A: np.array):
        A = np.ones((2,2))
        return A

    def pass_by_ref_sideEffect(A: np.array):
        A[0][0] = 2
        return A


    A = np.zeros((2,2))

    B = pass_by_ref(A)
    print("A =\n", A)
    print("B =\n", B)

    C = pass_by_ref_sideEffect(A)
    print("A =\n", A)
    print("C =\n", C)

output:

    A =
     [[0. 0.]
     [0. 0.]]
    B =
     [[1. 1.]
     [1. 1.]]
    A =
     [[2. 0.]
     [0. 0.]]
    C =
     [[2. 0.]
     [0. 0.]]

Why we have side effect on A after pass_by_ref_sideEffect and not with pass_by_ref?


Solution

  • This has nothing to do with how you are passing in the variable and everything to do with how assignment works. In pass_by_ref() this line A = np.ones((2,2)) creates a new array and assigns it to the local name A. The original array object still exists, but A no longer refers to it. In the other case you are manipulating the original array by assigning to an element of it with A[0][0] = 2.

    If you want to have a side effect in the first case, then assign to a slice of A like this:

    def pass_by_ref(A: np.array):
        A[:,:] = np.ones((2,2))
        return A
    
    A = np.zeros((2,2))
    B = pass_by_ref(A)
    
    print(A)
    [[1., 1.],
     [1., 1.]]
    
    print(B)
    [[1., 1.],
     [1., 1.]]
    

    Here's an example that demonstrates this without passing variables into functions:

    In [1]: import numpy as np
    
    In [2]: A = np.zeros((2,2))
    
    In [3]: B = A
    
    In [4]: B
    Out[4]:
    array([[0., 0.],
           [0., 0.]])
    
    In [5]: A[:,:] = np.ones((2,2))
    
    In [6]: B
    Out[6]:
    array([[1., 1.],
           [1., 1.]])