Spec-Zone.ru › NumPy 2.0

Копии и представления

При работе с массивами NumPy можно напрямую получить доступ к внутреннему буферу данных, используя представление, не копируя данные. Это обеспечивает высокую производительность, но также может привести к нежелательным проблемам, если пользователь не понимает, как это работает. Поэтому важно знать разницу между этими двумя терминами и какие операции возвращают копии, а какие — представления.

Массив NumPy — это структура данных, состоящая из двух частей: смежного буфера данных с фактическими элементами данных и метаданных, содержащих информацию о буфере данных. Метаданные включают тип данных, шаги и другую важную информацию, которая помогает легко управлять ndarray. Подробный обзор см. в разделе Внутренняя организация массивов NumPy.

Представление

Можно получить доступ к массиву по-другому, просто изменив некоторые метаданные, такие как шаг и тип данных, не изменяя буфер данных. Это создает новый способ просмотра данных, и эти новые массивы называются представлениями. Буфер данных остается неизменным, поэтому любые изменения, внесенные в представление, отражаются в исходной копии. Представление можно принудительно создать с помощью метода ndarray.view.

Копия

Когда новый массив создаётся путём дублирования буфера данных и метаданных, он называется копией. Изменения, внесенные в копию, не отражаются в исходном массиве. Создание копии медленнее и потребляет больше памяти, но иногда это необходимо. Копию можно создать, используя ndarray.copy.

Операции индексирования

См. также

Индексирование ndarrays

Представления создаются, когда элементы можно адресовать с помощью смещений и шагов в исходном массиве. Поэтому базовые операции индексирования всегда создают представления. Например:

>>> x = np.arange(10)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> y = x[1:3]  # creates a view
>>> y
array([1, 2])
>>> x[1:3] = [10, 11]
>>> x
array([ 0, 10, 11,  3,  4,  5,  6,  7,  8,  9])
>>> y
array([10, 11])

Здесь y изменяется, когда изменяется x, потому что это представление.

Расширенное индексирование, с другой стороны, всегда создаёт копии. Например:

>>> x = np.arange(9).reshape(3, 3)
>>> x
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> y = x[[1, 2]]
>>> y
array([[3, 4, 5],
       [6, 7, 8]])
>>> y.base is None
True

Здесь y является копией, как обозначено атрибутом base. Это также можно подтвердить, присвоив новые значения x[[1, 2]], что не повлияет на y:

>>> x[[1, 2]] = [[10, 11, 12], [13, 14, 15]]
>>> x
array([[ 0,  1,  2],
       [10, 11, 12],
       [13, 14, 15]])
>>> y
array([[3, 4, 5],
       [6, 7, 8]])

Следует отметить, что при присвоении x[[1, 2]] представление или копия не создаются, так как присвоение происходит непосредственно.

Другие операции

Функция numpy.reshape создаёт представление, если это возможно, или копию в противном случае. В большинстве случаев шаги можно изменить для изменения формы массива с помощью представления. Однако в некоторых случаях, когда массив становится несмежным (возможно, после операции ndarray.transpose), изменение формы с помощью изменения шагов невозможно и требуется копия. В этих случаях можно вызвать ошибку, присвоив новую форму атрибуту формы массива. Например:

>>> x = np.ones((2, 3))
>>> y = x.T  # makes the array non-contiguous
>>> y
array([[1., 1.],
       [1., 1.],
       [1., 1.]])
>>> z = y.view()
>>> z.shape = 6
Traceback (most recent call last):
   ...
AttributeError: Incompatible shape for in-place modification. Use
`.reshape()` to make a copy with the desired shape.

Рассмотрим пример другой операции, ravel возвращает сплошное уплощенное представление массива, где это возможно. С другой стороны, ndarray.flatten всегда возвращает уплощенную копию массива. Однако для гарантии представления в большинстве случаев, x.reshape(-1) может быть предпочтительнее.

Как определить, является ли массив представлением или копией

Атрибут base ndarray позволяет легко определить, является ли массив представлением или копией. Атрибут base представления возвращает исходный массив, а для копии он возвращает None.

>>> x = np.arange(9)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> y = x.reshape(3, 3)
>>> y
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> y.base  # .reshape() creates a view
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> z = y[[2, 1]]
>>> z
array([[6, 7, 8],
       [3, 4, 5]])
>>> z.base is None  # advanced indexing creates a copy
True

Обратите внимание, что атрибут base не следует использовать для определения, является ли объект ndarray новым; только для того, чтобы определить, является ли он представлением или копией другого ndarray.

© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/user/basics.copies.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API