Большая часть путаницы здесь заключается в характере a[0]
в случае массива.
Для списка b[0]
является действительным элементом b
.Мы можем проиллюстрировать это, создав список изменяемых элементов (другие списки):
In [22]: b = [[0],[1],[2],[3]]
In [23]: b1 = b[0]
In [24]: b1
Out[24]: [0]
In [25]: b[0].append(10)
In [26]: b
Out[26]: [[0, 10], [1], [2], [3]]
In [27]: b1
Out[27]: [0, 10]
In [28]: b1.append(20)
In [29]: b
Out[29]: [[0, 10, 20], [1], [2], [3]]
Мутирование b[0]
и b1
действуют на один и тот же объект.
Для массива:
In [35]: a = np.array([0,1,2,3])
In [36]: c = a.view()
In [37]: a1 = a[0]
In [38]: a += 1
In [39]: a
Out[39]: array([1, 2, 3, 4])
In [40]: c
Out[40]: array([1, 2, 3, 4])
In [41]: a1
Out[41]: 0
изменение на месте в a
не меняет a1
, даже если оно изменилось c
.
__array_interface__
показывает нам, где хранится буфер данных для массива- в свободном смысле думать об этом как об адресе памяти этого буфера.
In [42]: a.__array_interface__['data']
Out[42]: (31233216, False)
In [43]: c.__array_interface__['data']
Out[43]: (31233216, False)
In [44]: a1.__array_interface__['data']
Out[44]: (28513712, False)
Представление имеет тот же буфер данных.Но a1
нет.a[0:1]
- это единственный элемент view
из a
, который совместно использует буфер данных.
In [45]: a[0:1].__array_interface__['data']
Out[45]: (31233216, False)
In [46]: a[1:2].__array_interface__['data'] # 8 bytes over
Out[46]: (31233224, False)
Так что id(a[0])
почти ничего не говорит нам о a
.Сравнение идентификаторов только говорит нам о том, как используются слоты памяти при создании объектов Python или нет.