Two NumPy array objects can expose different selections while referring to overlapping bytes in the same data buffer. That distinction determines whether an in-place write through a derived array also changes its source.

Use np.shares_memory(source, candidate) for a pair-specific overlap check. The .base attribute shows whether an array is backed by another object, but a chained view may have a different base object than the source being compared.

Basic slicing creates a view, while advanced indexing and .copy() create independent arrays. Exact overlap checks can be expensive for pathological stride layouts; a finite max_work limit or np.may_share_memory() provides the documented bounded or conservative alternative.

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

  1. Define the source array and three derived arrays in array-check-view-copy.py.
    array-check-view-copy.py
    import numpy as np
     
    source = np.arange(6)
    basic_slice = source[1:4]
    advanced_index = source[[1, 2, 3]]
    explicit_copy = source[1:4].copy()
  2. Add pair-specific overlap checks below the array definitions.
    candidates = {
        "basic_slice": basic_slice,
        "advanced_index": advanced_index,
        "explicit_copy": explicit_copy,
    }
     
    for name, candidate in candidates.items():
        print(
            f"{name}: shares_memory={np.shares_memory(source, candidate)}, "
            f"base_is_none={candidate.base is None}"
        )
  3. Append mutations that expose whether each derived array writes through to source.
    basic_slice[0] = 99
    advanced_index[1] = 77
    explicit_copy[2] = 55
     
    print("source after edits:", source)
    print("basic_slice after edit:", basic_slice)
    print("advanced_index after edit:", advanced_index)
    print("explicit_copy after edit:", explicit_copy)
  4. Consolidate the sections into the completed array-check-view-copy.py file.
    array-check-view-copy.py
    import numpy as np
     
    source = np.arange(6)
    basic_slice = source[1:4]
    advanced_index = source[[1, 2, 3]]
    explicit_copy = source[1:4].copy()
     
    candidates = {
        "basic_slice": basic_slice,
        "advanced_index": advanced_index,
        "explicit_copy": explicit_copy,
    }
     
    for name, candidate in candidates.items():
        print(
            f"{name}: shares_memory={np.shares_memory(source, candidate)}, "
            f"base_is_none={candidate.base is None}"
        )
     
    basic_slice[0] = 99
    advanced_index[1] = 77
    explicit_copy[2] = 55
     
    print("source after edits:", source)
    print("basic_slice after edit:", basic_slice)
    print("advanced_index after edit:", advanced_index)
    print("explicit_copy after edit:", explicit_copy)
  5. Run the completed script to compare the overlap checks with the edit results.
    $ python3 array-check-view-copy.py
    basic_slice: shares_memory=True, base_is_none=False
    advanced_index: shares_memory=False, base_is_none=True
    explicit_copy: shares_memory=False, 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]
    explicit_copy after edit: [ 1  2 55]

    The basic slice reports True and propagates 99 into source. Both copies report False, and their 77 and 55 edits remain isolated. The .base values agree for these direct examples, but np.shares_memory() is the pair-specific check.