В отличие от объекта списка Python, который содержит ссылки на первый уровень объектов элементов (который, в свою очередь, может ссылаться на более глубокие уровни объектов), массив NumPy ссылается только на один буфер данных, в котором хранятся все значения элементов для всех измерениймассив, и нет иерархии объектов элементов за пределами этого буфера данных.
Мелкая копия списка будет содержать копии первого уровня ссылок на элементы и делиться ссылочными объектными элементами с исходным списком.Менее очевидно, что должна содержать поверхностная копия массива NumPy.Должен ли он ( A ) совместно использовать буфер данных с оригиналом или ( B ) иметь свою собственную копию (что фактически делает ее глубокой копией)?
A представление массива NumPy является неглубокой копией в смысле A, то есть он ссылается на тот же буфер данных, что и оригинал, поэтому изменения в исходных данных влияют на данные представления и наоборот.
Библиотечная функция copy.copy () должна создавать поверхностную копию своего аргумента, но при применении к массиву NumPy она создает поверхностную копию в смысле B, то есть новый массив получает свою собственную копиюбуфер данных, поэтому изменения в одном массиве не влияют на другой.
Вот некоторый код, показывающий различные способы копирования / просмотра массивов NumPy:
import numpy as np
import copy
x = np.array([10, 11, 12, 13])
# Create views of x (shallow copies sharing data) in 2 different ways
x_view1 = x.view()
x_view2 = x[:] # Creates a view using a slice
# Create full copies of x (not sharing data) in 2 different ways
x_copy1 = x.copy()
x_copy2 = copy.copy(x) # Calls x.__copy__() which creates a full copy of x
# Change some array elements to see what happens
x[0] = 555 # Affects x, x_view1, and x_view2
x_view1[1] = 666 # Affects x, x_view1, and x_view2
x_view2[2] = 777 # Affects x, x_view1, and x_view2
x_copy1[0] = 888 # Affects only x_copy1
x_copy2[0] = 999 # Affects only x_copy2
print(x) # [555 666 777 13]
print(x_view1) # [555 666 777 13]
print(x_view2) # [555 666 777 13]
print(x_copy1) # [888 11 12 13]
print(x_copy2) # [999 11 12 13]
Приведенный выше пример создает представлениявесь диапазон индекса исходного массива и с теми же атрибутами массива, что и у исходного, что не очень интересно (можно заменить простым псевдонимом, например, x_alias = x).Что делает представления мощными, так это то, что они могут быть видами выбранных частей оригинала и иметь разные атрибуты.Это продемонстрировано в следующих нескольких строках кода, которые расширяют приведенный выше пример:
x_view3 = x[::2].reshape(2,1) # Creates a reshaped view of every 2nd element of x
print(x_view3) # [[555]
# [777]]
x_view3[1] = 333 # Affects 2nd element of x_view3 and 3rd element of x
print(x) # [555 666 333 13]
print(x_view3) # [[555]
# [333]]