In [118]: a = np.array([1.,2.,3.,4.,5.])
...: av = a.view()
In [119]: a
Out[119]: array([1., 2., 3., 4., 5.])
In [120]: av
Out[120]: array([1., 2., 3., 4., 5.])
Массив - это объект с атрибутами, такими как dtype
и shape
, плюс указатель на буфер данных (base
).Мы можем получить сводку этих атрибутов с помощью:
In [121]: a.__array_interface__
Out[121]:
{'data': (69293648, False),
'strides': None,
'descr': [('', '<f8')],
'typestr': '<f8',
'shape': (5,),
'version': 3}
av
- это новый объект массива, но он имеет те же атрибуты, включая data
:
In [122]: av.__array_interface__
Out[122]:
{'data': (69293648, False), # same value as for a
'strides': None,
'descr': [('', '<f8')],
'typestr': '<f8',
'shape': (5,),
'version': 3}
сравните это с copy
:
In [123]: bv = a.copy()
In [124]: bv.__array_interface__
Out[124]:
{'data': (77843920, False),
'strides': None,
'descr': [('', '<f8')],
'typestr': '<f8',
'shape': (5,),
'version': 3}
Другие виды могут иметь разные значения - срезы имеют различную форму и шаги и т. д. Но буфер данных будет одинаковым (фактическое число, показанное в __array_interface__['data']
, может бытьнемного по-другому, указывая на другой элемент в буфере.
Измените элемент на a
, и мы увидим это изменение также в av
- из-за общего буфера данных:
In [125]: a[0] =12
In [126]: av[0]
Out[126]: 12.0
In [127]: bv[0]
Out[127]: 1.0
Когда вы назначаете что-то еще для a
, av
не изменяется.
In [128]: a = 10
In [129]: a.__array_interface__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-129-3b348559b028> in <module>
----> 1 a.__array_interface__
AttributeError: 'int' object has no attribute '__array_interface__'
In [130]: av.__array_interface__
Out[130]:
{'data': (69293648, False),
'strides': None,
'descr': [('', '<f8')],
'typestr': '<f8',
'shape': (5,),
'version': 3}
a
- это целое число, а не массив. Буфер данных, который был изначально создан дляa
все еще существует, служа базой для av
. В противном случае исходный объект a
исчезнет.
Мне нужно определить этот последний оператор - из-за буферизации вывода ipython
, чтоОбъект массива все еще существует:
In [131]: Out[119].__array_interface__
Out[131]:
{'data': (69293648, False),
'strides': None,
'descr': [('', '<f8')],
'typestr': '<f8',
'shape': (5,),
'version': 3}
In [132]: Out[119][0]
Out[132]: 12.0
Я делаюybe должен был отобразить id(a)
и т. д., чтобы уточнить
In [133]: id(av)
Out[133]: 139992523130800
In [134]: id(Out[119])
Out[134]: 139992142353312
изменения в av
появляются в Out[119]
, но не в a
- потому что a
- это совершенно другой объект.
In [144]: av[1] = 100
In [145]: Out[119]
Out[145]: array([ 12., 100., 3., 4., 5.])
In [146]: a
Out[146]: 10
Итак, на каком-то уровне вам необходимо понять природу переменных и объектов Python.Например, b=a
просто создает другое имя или ссылку на тот же объект, а не копию.b = a.copy()
делает копию, но детали этой копии зависят от класса объекта.numpy
добавляет вариант copy
, view
, что позволяет экономить время и память.Но вы должны знать кое-что о его механизме хранения данных, чтобы понять это.