Search code examples
pythonpython-3.xnumpypass-by-referencepass-by-value

Python - Why ndarray passed by value changes outside function?


I have the following function:

def a_function(foo):
    bar = foo
    print("bar1: ", bar, id(foo))
    bar[0] = foo[2]
    print("bar2: ", bar, id(foo))

Call with list as parameter:

foo = [0, 1, 2, 3, 4, 5, 6, 7, 8]
print("foo1: ", foo, id(foo))
a_function(foo[:])
print("foo2: ", foo, id(foo))

Output:

foo1:  [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901565768
bar1:  [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901566472
bar2:  [2, 1, 2, 3, 4, 5, 6, 7, 8] 140118901566472
foo2:  [0, 1, 2, 3, 4, 5, 6, 7, 8] 140118901565768

Call with ndarray as parameter:

foo = np.arange(0,9)
print("foo1: ", foo, id(foo))
a_function(foo[:])
print("foo2: ", foo, id(foo))

Output:

foo1:  [0 1 2 3 4 5 6 7 8] 139814139381760
bar1:  [0 1 2 3 4 5 6 7 8] 139814115258000
bar2:  [2 1 2 3 4 5 6 7 8] 139814115258000
foo2:  [2 1 2 3 4 5 6 7 8] 139814139381760

I passed it as a copy foo[:] even copied again inside the function and also it has it's own id. However foo2 changed it's value outside the scope of the function when it's a ndarray. How is this possible?


Solution

  • In Python,

    bar = foo
    

    does not make a copy. bar and foo reference the same array object.

    This action makes a copy of a list, but just a view of an array:

    foo[:]
    

    You need to use foo.copy() if you want to isolate changes in bar from foo.

    I'd suggest reviewing some of the basic numpy documentation, especially the stuff about views and copies.