我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

作为目前python代码中强大又常见的第三方数组类型,ndarray类型,在创建数组的时候有个order参数,可以控制元素在内存中的存储顺序。就是说在ndarray形成的时候,输入的元素的实际位置,受到order参数的控制,控制其元素的实际摆放位置。

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - ndarray-order
如何解读numpy中ndarray数组的order存储顺序参数?(图7-1)

苏南大叔的"程序如此灵动"博客,记录苏南大叔的编程经验内容。本文测试环境:win10python@3.11.0numpy@1.24.2

以前有首歌叫做“都选C”来着吧?其实很适合本文,对于和ndarray扯上关系的order参数,选择C是大概率没有问题的。选择F大概率是会出一些意外的。

前文回顾

本文内容的正确理解,可能需要您了解如下内容:

重要结论:order!!!

对于pythonndarray,相关选项就一个:fortran_order!取值是True或者False!所以,不论本文中的后续内容如何说明,极有可能的真相就是:就是二分法,是不是按列读取!fortran_order

可以把ndarray保存到.npy或者.npz文件里面,就可以看到其描述类似为:

{'descr': '<U1', 'fortran_order': False, 'shape': (2, 4), }

有哪些order?

可用的order有四个,但是常见的就两个。

参数用途说明
C按行读取最常见
F按列读取相对不常见
K按内存读取--
A按行或列读取对于python来说,A就等于C

使用order参数的函数有如下几个,默认order参数都是C

  • numpy.copy()
  • numpy.ravel()
  • numpy.flatten()
  • numpy.reshape()(无法使用K
  • numpy.zeros()
  • numpy.ones()
  • 其它

只有定义numpy.array()中的order默认是K(内存)。

order不影响ndarray的视图

order不影响ndarray的视图。也就是说,无论order写的是什么值,最终展现出来的视图(通俗的说,print出来的数据)都是一样的。只是影响成员在内存中的存放顺序,但是这个对于大多数人来说,是无感的。

下面的代码中(不限于这些),虽然order设置不同,但是,这些变量的打印值一模一样。

import numpy as np

a = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='C')
b = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='F')
c = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='K')
d = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='A')
print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)

输出:

a: [['苏' '南' '大' '叔']
 ['技' '术' '博' '客']]
b: [['苏' '南' '大' '叔']
 ['技' '术' '博' '客']]
c: [['苏' '南' '大' '叔']
 ['技' '术' '博' '客']]
d: [['苏' '南' '大' '叔']
 ['技' '术' '博' '客']]

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 1
如何解读numpy中ndarray数组的order存储顺序参数?(图7-2)

使用.strides可以做部分区分

因为实际情况下,order参数A效果等于CK效果也很可能等于C。所以,使用.strides是可以区分F的情况出来。

strides:进展,步法。

正常情况下来说,一个元素占四个字节(也不一定,这里就是举个简单的例子。)

测试代码:

import numpy as np

a = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='C')
b = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='F')
c = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='K')
d = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='A')
print("C:", a.strides)
print("F:", b.strides)
print("K:", c.strides)
print("A:", d.strides)

输出:

C: (16, 4)
F: (4, 8)
K: (16, 4)
A: (16, 4)

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 2
如何解读numpy中ndarray数组的order存储顺序参数?(图7-3)

可以看到:

order取值第一维度(行)内存差值第二维度(列)内存差值
C/K/A(16,4)4个元素*4个字节=16字节4个字节
F(4,8)4个字节8个字节

查看内存中的实际排序

可以利用了数据扁平化函数的order='K'参数来进行查看。[用魔法打败魔法]。
这里可以使用.zeval().flatten()来实现数据的扁平化,但是不能使用reshape(-1),会得到错误提示信息:

    d2 = d.reshape(-1,order="K")
         ^^^^^^^^^^^^^^^^^^^^^^^
ValueError: order 'K' is not permitted for reshaping

参考文章:

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 不支持reshape-k参数
如何解读numpy中ndarray数组的order存储顺序参数?(图7-4)

测试order='C/K/A'

import numpy as np

a = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='C')
c = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='K')
d = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='A')

a2 = a.flatten(order="K")
print(a2, a2.strides)
c2 = c.flatten(order="K")
print(c2, c2.strides)
d2 = d.flatten(order="K")
print(d2, d2.strides)

输出:

['苏' '南' '大' '叔' '技' '术' '博' '客'] (4,)
['苏' '南' '大' '叔' '技' '术' '博' '客'] (4,)
['苏' '南' '大' '叔' '技' '术' '博' '客'] (4,)

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 读取内存中的顺序
如何解读numpy中ndarray数组的order存储顺序参数?(图7-5)

测试order='F'

import numpy as np

b = np.array([["苏", "南", "大", "叔"], ["技", "术", "博", "客"]], order='F')
b2 = b.ravel(order="K")
print(b2, b2.strides)
# b2 = b.flatten(order="K")
# print(b2, b2.strides)

输出:

['苏' '技' '南' '术' '大' '博' '叔' '客'] (4,)

上面的代码显示:内存中的值是按着一列一列的顺序存储的。

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 检测F的内存存储顺序
如何解读numpy中ndarray数组的order存储顺序参数?(图7-6)

import numpy as np

b0 = [["苏", "南", "大", "叔"], ["技", "术", "博", "客"]]
b = np.array(b0, order='F').swapaxes(1,0)
print(b, b.strides)
b2 = b.flatten(order="K")
print(b2, b2.strides)

输出:

[['苏' '技']
 ['南' '术']
 ['大' '博']
 ['叔' '客']] (8, 4)
['苏' '技' '南' '术' '大' '博' '叔' '客'] (4,)

这个代码显示:虽然中间值b被转置了,但是内存中的存储顺序依然没有发生改变。

相关文章:

苏南大叔:如何解读numpy中ndarray数组的order存储顺序参数? - 忽视中间变化
如何解读numpy中ndarray数组的order存储顺序参数?(图7-7)

结论

可见,order参数在定义的时候,没有什么大的影响的。但是对其成员进行读取的时候,根据order的不同,可能会有不同的结果出现。

更多苏南大叔的python经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   python