English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

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

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

Различие между дубликатом и представлением

Основное различие между дубликатом и представлением в том, что дубликат - это новый массив, а представление - это только представление исходного массива.Дубликат содержит данные, любое изменение в дубликате не влияет на исходный массив, и наоборот, любое изменение в исходном массиве не влияет на дубликат.Представление не содержит данных, любая изменение в представлении влияет на исходный массив, и наоборот, любое изменение в исходном массиве влияет на представление.

Представление обычно происходит:

1. Операции нарезки numpy возвращают представление исходных данных2. Создание представления вызовом функции view() класса ndarray

Дублирование обычно происходит:

Операции нарезки Python последовательности, вызов функции deepCopy()Создание дубликата вызовом функции copy() класса ndarray

Без копирования

Простое присвоение не создает дубликата объекта массива. Напротив, оно использует один и тот же id() для доступа к нему. Функция id() возвращает уникальный идентификатор Python объекта, аналогичный указателю в C. Кроме того, любая изменениия в одном массиве отражаются на другом. Например, изменение формы одного массива изменяет форму другого массива.

>>> import numpy as np
>>> a = np.arange(6)
>>> print ('Наш массив:', a)
Наш массив: [0 1 2 3 4 5]
>>> print ('Вызов функции id():', id(a))
Вызов функции id(): 4553321728
>>> b = a
>>> print(b)
[0 1 2 3 4 5]
>>> print('b имеет идентичный id():', id(b))
b имеет идентичный id() 4553321728
>>> b.shape = 3,2
>>> print(b)
[[0 1]
 [2 3]
 [4 5]]
>>> print(a)
[[0 1]
 [2 3]
 [4 5]]
>>>

Представление или поверхностная копия

ndarray.view() создаст новый объект массива, метод создания нового массива изменит размерность, но не размерность исходных данных.

import numpy as np 
 
 # В最开始 a был массивом 3x2
a = np.arange(6).reshape(3,2) 
print ('Массив a:')
print (a)
print('Создание представления a:')
b = a.view() 
print (b)
print('id() двух массивов различаются:')
print('id a:')
print(id(a))
print('id b:')
print(id(b))
 # Изменение формы b не изменяет a
b.shape = 2,3
print('Форма b:')
print (b)
print('Форма a:')
print (a)

Результат вывода:

Массив a:
[[0 1]
 [2 3]
 [4 5]]
Создание представления a:
[[0 1]
 [2 3]
 [4 5]]
id() двух массивов различаются:
id a:
4314786992
id b:
4315171296
Форма b:
[[0 1 2]
 [3 4 5]
Форма a:
[[0 1]
 [2 3]
 [4 5]]

Использование срезов для создания представлений и изменения данных влияет на исходный массив:

import numpy as np 
arr = np.arange(12)
print('Наш массив:')
print(arr)
print('Создание среза:')
a=arr[2:]
b=arr[2:]
a[1]=123456
b[2]=23445
print(arr)
print(id(a), id(b), id(arr[3:]))

Результат вывода:

Наш массив:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
Создание среза:
[ 0 1 2 123456 23445 5 6 7 8 9
     10 11]
4669930672 4444330304 4670012352
Процесс завершен с кодом выхода 0

Переменные a, b являются частью представления arr, изменения в представлении будут напрямую отражаться на исходных данных. Но если мы рассмотрим id a, b, они различаются, то есть, хотя представления указывают на исходные данные, они все же отличаются от значений ссылки.

Копия или глубокая копия

Функция ndarray.copy() создает копию. Изменение данных в копии не влияет на исходные данные, они физически не находятся в одном и том же месте.

import numpy as np 
 
a = np.array([[10,10], [2,3], [4,5]]) 
print ('Массив a:')
print (a)
print ('Создать глубокую копию a:')
b = a.copy() 
print ('Массив b:')
print (b)
 # b и a не делят ни одного контента 
print ('Можем ли мы записать в b чтобы записать в a ?')
print (b is a)
print ('Изменить содержимое b:')
b[0,0] = 100 
print ('Измененный массив b:')
print (b)
print ('a оставить без изменений:')
print (a)

Результат вывода:

Массив a:
[[10 10]
 [ 2 3]
 [ 4 5]]
Создать глубокую копию a:
Массив b:
[[10 10]
 [ 2 3]
 [ 4 5]]
Можем ли мы записать в b чтобы записать в a ?
False
Изменить содержимое b:
Измененный массив b:
[[100 10]
 [ 2 3]
 [ 4 5]]
a оставить без изменений:
[[10 10]
 [ 2 3]
 [ 4 5]]