Search code examples
pythonnumpyreturnarguments

numpy array passed as argument to function, and returned array are the same


function looks like:

def mutate_color(tri):
    out = tri.copy()
    out[3][np.random.randint(3)] = np.random.randint(256)
return out

one object looks like:

TRI_A = array([array([181, 75]), array([99, 9]), array([53, 15]),
array([18, 5, 19], dtype=uint8)], dtype=object)

<== this is a colored triangle, frist three are coordinates, the last one are RGB value.

But when I pass this (or some object like this to this function):

for example:

TRI_B = mutate_color(TRI_A)

I noticed that both TRI-B and TRI_A are modifed, I mean I use .copy() function, shouldn't TRI_A remain the same as the orignial and only B will be modifed?

Please Help.


Solution

  • The data type of TRI_A is object, so the values that are actually stored in the array are the pointers to the various objects (in this case, several different numpy arrays). When the copy() method creates a new object array, it only copies the pointers. It does not recursively copy all the Python objects that are pointed to by the numpy array.

    This is explained further in the docstring of numpy.copy. In particular,

    Note that np.copy is a shallow copy and will not copy object
    elements within arrays. This is mainly important for arrays
    containing Python objects. The new array will contain the
    same object which may lead to surprises if that object can
    be modified (is mutable):
    
    >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
    >>> b = np.copy(a)
    >>> b[2][0] = 10
    >>> a
    array([1, 'm', list([10, 3, 4])], dtype=object)
    
    To ensure all elements within an ``object`` array are copied,
    use `copy.deepcopy`:
    
    >>> import copy
    >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
    >>> c = copy.deepcopy(a)
    >>> c[2][0] = 10
    >>> c
    array([1, 'm', list([10, 3, 4])], dtype=object)
    >>> a
    array([1, 'm', list([2, 3, 4])], dtype=object)