# 数组类型 In [1]: ```py from numpy import * ``` 之前已经看过整数数组和布尔数组,除此之外还有浮点数数组和复数数组。 ## 复数数组 产生一个复数数组: In [2]: ```py a = array([1 + 1j, 2, 3, 4]) ``` **Python**会自动判断数组的类型: In [3]: ```py a.dtype ``` Out[3]: ```py dtype('complex128') ``` 对于复数我们可以查看它的实部和虚部: In [4]: ```py a.real ``` Out[4]: ```py array([ 1., 2., 3., 4.]) ``` In [5]: ```py a.imag ``` Out[5]: ```py array([ 1., 0., 0., 0.]) ``` 还可以设置它们的值: In [6]: ```py a.imag = [1,2,3,4] ``` 查看 `a`: In [7]: ```py a ``` Out[7]: ```py array([ 1.+1.j, 2.+2.j, 3.+3.j, 4.+4.j]) ``` 查看复共轭: In [8]: ```py a.conj() ``` Out[8]: ```py array([ 1.-1.j, 2.-2.j, 3.-3.j, 4.-4.j]) ``` 事实上,这些属性方法可以用在浮点数或者整数数组上: In [9]: ```py a = array([0.,1,2,3]) a.dtype ``` Out[9]: ```py dtype('float64') ``` In [10]: ```py a.real ``` Out[10]: ```py array([ 0., 1., 2., 3.]) ``` In [11]: ```py a.imag ``` Out[11]: ```py array([ 0., 0., 0., 0.]) ``` In [12]: ```py a.conj() ``` Out[12]: ```py array([ 0., 1., 2., 3.]) ``` 但这里,虚部是只读的,并不能修改它的值: In [13]: ```py # 会报错 a.imag = [1,2,3,4] ``` ```py --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 1 # 会报错 ----> 2 a.imag = [1,2,3,4] TypeError: array does not have imaginary part to set ``` ## 指定数组类型 之前已经知道,构建数组的时候,数组会根据传入的内容自动判断类型: In [14]: ```py a = array([0,1.0,2,3]) ``` 对于浮点数,默认为双精度: In [15]: ```py a.dtype ``` Out[15]: ```py dtype('float64') ``` 查看所用字节(`8 bytes * 4`): In [16]: ```py a.nbytes ``` Out[16]: ```py 32 ``` 当然,我们也可以在构建的时候指定类型: In [17]: ```py a = array([0,1.0,2,3], dtype=float32) ``` 此时类型为单精度浮点数: In [18]: ```py a.dtype ``` Out[18]: ```py dtype('float32') ``` 查看所用字节(`4 bytes * 4`): In [19]: ```py a.nbytes ``` Out[19]: ```py 16 ``` 除此之外,还可以指定有无符号,例如无符号整数: In [20]: ```py a = array([0,1,2,3], dtype=uint8) a.dtype ``` Out[20]: ```py dtype('uint8') ``` `uint8` 只使用一个字节,表示 `0` 到 `255` 的整数。 还可以从二进制数据中读取。 先写入二进制数据: In [21]: ```py a = array([102,111,212], dtype=uint8) a.tofile('foo.dat') ``` 从数据中读入,要指定类型: In [22]: ```py b = frombuffer('foo', dtype=uint8) b ``` Out[22]: ```py array([102, 111, 111], dtype=uint8) ``` 清理数据文件: In [23]: ```py import os os.remove('foo.dat') ``` `0-255` 的数字可以表示ASCⅡ码,我们可以用 ord 函数来查看字符的ASCⅡ码值: In [24]: ```py ord('f') ``` Out[24]: ```py 102 ``` In [25]: ```py ord('S') ``` Out[25]: ```py 83 ``` ## Numpy 类型 具体如下: | 基本类型 | 可用的**Numpy**类型 | 备注 | | --- | --- | --- | | 布尔型 | `bool` | 占1个字节 | | 整型 | `int8, int16, int32, int64, int128, int` | `int` 跟**C**语言中的 `long` 一样大 | | 无符号整型 | `uint8, uint16, uint32, uint64, uint128, uint` | `uint` 跟**C**语言中的 `unsigned long` 一样大 | | 浮点数 | `float16, float32, float64, float, longfloat` | 默认为双精度 `float64` ,`longfloat` 精度大小与系统有关 | | 复数 | `complex64, complex128, complex, longcomplex` | 默认为 `complex128` ,即实部虚部都为双精度 | | 字符串 | `string, unicode` | 可以使用 `dtype=S4` 表示一个4字节字符串的数组 | | 对象 | `object` | 数组中可以使用任意值 | | Records | `void` | | | 时间 | `datetime64, timedelta64` | 任意类型的数组: In [26]: ```py a = array([1,1.2,'hello', [10,20,30]], dtype=object) ``` 乘法: In [27]: ```py a * 2 ``` Out[27]: ```py array([2, 2.4, 'hellohello', [10, 20, 30, 10, 20, 30]], dtype=object) ``` ## 类型转换 转换数组的类型: In [28]: ```py a = array([1.5, -3], dtype=float32) a ``` Out[28]: ```py array([ 1.5, -3\. ], dtype=float32) ``` ### asarray 函数 使用 `asarray` 函数: In [29]: ```py asarray(a, dtype=float64) ``` Out[29]: ```py array([ 1.5, -3\. ]) ``` In [30]: ```py asarray(a, dtype=uint8) ``` Out[30]: ```py array([ 1, 253], dtype=uint8) ``` `asarray` 不会修改原来数组的值: In [31]: ```py a ``` Out[31]: ```py array([ 1.5, -3\. ], dtype=float32) ``` 但当类型相同的时候,`asarray` 并不会产生新的对象,而是使用同一个引用: In [32]: ```py b = asarray(a, dtype=float32) ``` In [33]: ```py b is a ``` Out[33]: ```py True ``` 这么做的好处在与,`asarray` 不仅可以作用于数组,还可以将其他类型转化为数组。 有些时候为了保证我们的输入值是数组,我们需要将其使用 `asarray` 转化,当它已经是数组的时候,并不会产生新的对象,这样保证了效率。 In [34]: ```py asarray([1,2,3,4]) ``` Out[34]: ```py array([1, 2, 3, 4]) ``` ### astype 方法 `astype` 方法返回一个新数组: In [35]: ```py a.astype(float64) ``` Out[35]: ```py array([ 1.5, -3\. ]) ``` In [36]: ```py a.astype(uint8) ``` Out[36]: ```py array([ 1, 253], dtype=uint8) ``` astype也不会改变原来数组的值: In [37]: ```py a ``` Out[37]: ```py array([ 1.5, -3\. ], dtype=float32) ``` 另外,`astype` 总是返回原来数组的一份复制,即使转换的类型是相同的: In [38]: ```py b = a.astype(float32) print a print b ``` ```py [ 1.5 -3\. ] [ 1.5 -3\. ] ``` In [39]: ```py a is b ``` Out[39]: ```py False ``` ### view 方法 In [40]: ```py a = array((1,2,3,4), dtype=int32) a ``` Out[40]: ```py array([1, 2, 3, 4]) ``` `view` 会将 `a` 在内存中的表示看成是 `uint8` 进行解析: In [41]: ```py b = a.view(uint8) b ``` Out[41]: ```py array([1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0], dtype=uint8) ``` In [42]: ```py a[0] = 2**30 a ``` Out[42]: ```py array([1073741824, 2, 3, 4]) ``` 修改 `a` 会修改 `b` 的值,因为共用一块内存: In [43]: ```py b ``` Out[43]: ```py array([ 0, 0, 0, 64, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0], dtype=uint8) ```