Простая иллюстрация трансляции - 1d со скаляром:
In [18]: x = np.arange(10)
In [19]: X,Y = np.broadcast_arrays(x,3)
In [20]: X
Out[20]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [21]: Y
Out[21]: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])
In [22]: Y.strides
Out[22]: (0,)
In [23]: X+Y
Out[23]: array([ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
In [24]: [i+j for i,j in zip(X,Y)]
Out[24]: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
При такой конструкции трудно доказать, что Y
не занимает столько памяти, сколько x
. Итак, давайте расширим x
вместо:
In [30]: x1 = np.broadcast_to(x,(3,10))
In [31]: x1
Out[31]:
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
In [32]: x.__array_interface__
Out[32]:
{'data': (30797968, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (10,),
'version': 3}
In [33]: x1.__array_interface__
Out[33]:
{'data': (30797968, True),
'strides': (0, 8),
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (3, 10),
'version': 3}
x1
акций x
буфер данных. Дополнительная память не используется (за исключением самого объекта массива).
И превратить скаляр в 2d:
In [34]: x2,y2 = np.broadcast_arrays(x1,Y)
In [35]: y2.strides
Out[35]: (0, 0)