我看不出有太大差异的证据。您可以对非常大的数组进行时间测试。基本上都摆弄形状,可能还有步伐。 __array_interface__ 是访问此信息的好方法。例如:
In [94]: b.__array_interface__
Out[94]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (5,),
'strides': None,
'typestr': '<f8',
'version': 3}
In [95]: b[None,:].__array_interface__
Out[95]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (1, 5),
'strides': (0, 8),
'typestr': '<f8',
'version': 3}
In [96]: b.reshape(1,5).__array_interface__
Out[96]:
{'data': (162400368, False),
'descr': [('', '<f8')],
'shape': (1, 5),
'strides': None,
'typestr': '<f8',
'version': 3}
两者都创建一个视图,使用与原始相同的data 缓冲区。形状相同,但 reshape 不会改变 strides。 reshape 允许您指定 order。
而.flags 显示C_CONTIGUOUS 标志的差异。
reshape 可能会更快,因为它所做的更改更少。但无论哪种方式,操作都不应该对较大计算的时间产生太大影响。
例如大号b
In [123]: timeit np.outer(b.reshape(1,-1),b)
1 loops, best of 3: 288 ms per loop
In [124]: timeit np.outer(b[None,:],b)
1 loops, best of 3: 287 ms per loop
有趣的观察:b.reshape(1,4).strides -> (32, 8)
这是我的猜测。 .__array_interface__ 显示底层属性,.strides 更像是一个属性(尽管它可能都隐藏在 C 代码中)。默认基础值为None,当需要计算(或用.strides 显示)时,它会根据形状和项目大小计算它。 32 是到第一行 (4x8) 末端的距离。 np.ones((2,4)).strides 具有相同的 (32,8)(和 None 在 __array_interface__。
另一方面,b[None,:] 正在为广播做准备。广播时,重复使用现有值。这就是(0,8) 中的0 所做的。
In [147]: b1=np.broadcast_arrays(b,np.zeros((2,1)))[0]
In [148]: b1.shape
Out[148]: (2, 5000)
In [149]: b1.strides
Out[149]: (0, 8)
In [150]: b1.__array_interface__
Out[150]:
{'data': (3023336880L, False),
'descr': [('', '<f8')],
'shape': (2, 5),
'strides': (0, 8),
'typestr': '<f8',
'version': 3}
b1 与 np.ones((2,5)) 显示相同,但只有 5 个项目。
np.broadcast_arrays 是/numpy/lib/stride_tricks.py 中的一个函数。它使用来自同一文件的as_strided。这些函数直接使用 shape 和 strides 属性。