NumPy arrays can share one data buffer while presenting different shapes, positions, or strides. Checking the relationship between a source array and a derived array matters before mutating slices, passing arrays into code that writes in place, or deciding whether an intermediate result can be changed independently.

Basic slicing normally creates a view because NumPy can describe the selected values with metadata that points back into the original buffer. Advanced indexing with integer lists or boolean masks creates a new array with copied data, so edits to that result do not propagate to the source.

Use np.shares_memory(source, candidate) for the direct overlap check and treat .base as supporting context. Chained views and some intermediate arrays can make .base point to another owner rather than the source object being checked.

Steps to check whether a NumPy array is a view or copy:

  1. Create a script that compares a basic slice, an advanced-index result, and an explicit copy.
    array-check-view-copy.py
    import numpy as np
     
    source = np.arange(6)
    basic_slice = source[1:4]
    advanced_index = source[[1, 2, 3]]
    isolated_slice = source[1:4].copy()
     
    print("source before:")
    print(source)
    print()
     
    print("basic_slice shares memory:", np.shares_memory(source, basic_slice))
    print("advanced_index shares memory:", np.shares_memory(source, advanced_index))
    print("isolated_slice shares memory:", np.shares_memory(source, isolated_slice))
    print("basic_slice.base is None:", basic_slice.base is None)
    print("advanced_index.base is None:", advanced_index.base is None)
    print()
     
    basic_slice[0] = 99
    advanced_index[1] = 77
    isolated_slice[2] = 55
     
    print("source after edits:")
    print(source)
    print()
    print("basic_slice after edit:")
    print(basic_slice)
    print()
    print("advanced_index after edit:")
    print(advanced_index)
    print()
    print("isolated_slice after edit:")
    print(isolated_slice)
  2. Run the script.
    $ python array-check-view-copy.py
    source before:
    [0 1 2 3 4 5]
    
    basic_slice shares memory: True
    advanced_index shares memory: False
    isolated_slice shares memory: False
    basic_slice.base is None: False
    advanced_index.base is None: True
    
    source after edits:
    [ 0 99  2  3  4  5]
    
    basic_slice after edit:
    [99  2  3]
    
    advanced_index after edit:
    [ 1 77  3]
    
    isolated_slice after edit:
    [ 1  2 55]

    np.shares_memory(source, candidate) returns True only when the two arrays overlap in memory. For unusual stride-trick arrays, set max_work or use np.may_share_memory() as a conservative pre-check.

  3. Check the memory-sharing lines.

    basic_slice shares memory with source, while advanced_index and isolated_slice do not.

  4. Compare the edit results.

    The 99 written through basic_slice appears in source. The 77 written into advanced_index stays out of source because advanced indexing created a copy.

  5. Treat .copy() as the safe boundary before in-place edits to a slice.

    isolated_slice changes to [ 1 2 55] while source remains [ 0 99 2 3 4 5], so the explicit copy is isolated.
    Related: Index and slice arrays