我没有看到太大的差异证据。您可以对非常大的数组进行时间测试。基本上,两者都可以更改形状,可能还会更改步幅。 __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
缓冲区创建一个视图。形状相同,但重新整形不会改变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)
相同(而在__array_interface__
中是 None
)。
另一方面,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
函数。这些函数直接操作形状和跨度属性。
b.reshape(1,-1)
是一个方便的快捷方式。它将数组 b 转换为一行,列数自动确定。 - hpaulj