揭开Python科学计算的面纱
春牛春杖。無限春風來海上。便與春工。染得桃紅似肉紅。
春幡春勝。一陣春風吹酒醒。不似天涯。卷起楊花似雪花。
標準的Python中用列表保存一組值,可以當做數組使用,但是由于其值類型任意,所以列表中保存的是指針,這樣的話保存一個簡單的列表,例如:[1,2,3]需要三個指針和三個對象。對于數值運算來說這樣十分耗費內存和CPU。
Python提供了array 模塊,他所提供的array對象和列表不同,能直接保存數值和C語言的一維數組相似,但是他不支持多維數組,也沒有各種運算函數,因此也不適合做數值運算。
NumPy的誕生彌補了這些不足之處,NumPy提供了兩種基本的對象:
本文采用1.12版本
>>> import numpy as np >>> np.__version__ '1.12.0'ndarray對象
?
Numpy中使用ndarray對象來表示數組,他是整個庫的核心對象,NumPy中所有的函數都是圍繞這ndarray對象展開處理的。ndarray的結構不復雜,但是功能十分強大,不但可以用它大量高效的儲存數值元素,從而提高數組計算的運算速度,還可以用它和各種擴展庫進行數據交換。
創建
首先需要創建數組才能對其進行運算和操作。可以通過給array() , 函數傳遞Python的序列對象創建數組,如果傳遞的是多層嵌套的序列,將創建個多維數組:
>>> a = np.array([1,2,3,4]) >>> b = np.array([5,6,7,8]) >>> c = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,0]]) >>> a array([1, 2, 3, 4]) >>> b array([5, 6, 7, 8]) >>> c array([[1, 2, 3, 4],[4, 5, 6, 7],[7, 8, 9, 0]]) >>> a.shape # 查看數組的形狀可以通過其 shape屬性 (4,) >>> b.shape (4,) >>> c.shape (3, 4)數組a的shape屬性只有一個元素是因為他是一維數組 . 而數組C的shape屬性有兩個元素, 是因為他是二維數組 . 其元素的排序是從高維到低維 . 我們還可以通過修改數組的shape屬性,在保持數組元素個數不變的情況下,改變數組每個軸的長度.下面的例子講數組c的shape屬性改為(4,3), 注意從(3,4)到(4,3)不是對數組進行轉置, 而是改變每個軸的大小,數組元素在內存中的位置沒有變化
>>> c.shape = 4,3 >>> c array([[1, 2, 3],[4, 4, 5],[6, 7, 7],[8, 9, 0]])你應該可以發現(4,3)和(3,4)總結起來不還是12個基本元素么 ? 我們改變總容量行不行 ?
>>> c.shape = 4,2 Traceback (most recent call last):File "<input>", line 1, in <module>c.shape = 4,2 ValueError: cannot reshape array of size 12 into shape (4,2) >>> c.shape = 4,5 Traceback (most recent call last):File "<input>", line 1, in <module>c.shape = 4,5 ValueError: cannot reshape array of size 12 into shape (4,5)當我們設置某個軸的元素個數為 - 1 的時候, 講自動計算此軸的長度 . 由于數組c有12個元素因此下面的程序講c的shape屬性改為(2,6):
>>> c.shape = 2,-1 >>> c array([[1, 2, 3, 4, 4, 5],[6, 7, 7, 8, 9, 0]]) >>> c.shape (2, 6)如果是三維數組我們設置兩個 -1 呢 ?( 這個問題好像有點弱智 哈 )? 發生錯誤:只能指定一個位置的維度
>>> c = np.array([[[1,2,3,4],[4,5,6,7],[7,8,9,0]],[[1,2,3,4],[4,5,6,7],[7,8,9,0] ]]) >>> c.shape (2, 3, 4) >>> c.shape = 3,-1,-1 Traceback (most recent call last):File "<input>", line 1, in <module>c.shape = 3,-1,-1 ValueError: can only specify(指定) one unknown dimension(維度)使用數組的reshape方法, 可以創建指定形狀的新數組, 而原數組的形狀保持不變:
>>> a array([1, 2, 3, 4]) >>> d = a.reshape((2,2)) >>> d array([[1, 2],[3, 4]])匯編/C語言 中毒比較深的同學可能問了, 那么儲存方式呢 ? 其實數組a和d是共享儲存空間的,因此如果修改其中任意一個數組的元素都會同事修改另一個數組的內容, 注意在下面的例子中 , 數組d中的2也被改變成了100:(很好,很強大.)
>>> a array([1, 2, 3, 4]) >>> d = a.reshape((2,2)) >>> d array([[1, 2],[3, 4]]) >>> a[1] 2 >>> a[1] = 100 >>> a array([ 1, 100, 3, 4]) >>> d array([[ 1, 100],[ 3, 4]])元素類型
數組的元素類型可以通過dtype來獲得, 在前面的例子中, 創建數組所用到的序列的元素都是證書, 因此創建的數組的元素類型也都是整數, 我用的是Ubuntu64位, 所以我顯示的類型是int類型64位, 如果你的是32 位可能你用的是32位的系統.
>>> c array([[1, 2, 3, 4, 4, 5],[6, 7, 7, 8, 9, 0]]) >>> c.dtype dtype('int64')如果有編譯器有代碼提示的同學可能就會發現, 那個dtype了, 在沒有介紹前面的東西的時候你可能還以為這是個什么鬼 ? 現在應該知道他是用于指定元素類型用的了吧?
>>> ai32 = np.array( ┌──────────────────────────────────────────────────────────────┐ │ np.array: (object, dtype=None, copy=True, order='K', │ │ subok=False, ndmin=0) │ │ array array2string array_equal │ │ array_equiv array_repr array_split │ │ array_str │ │ array(object, dtype=None, copy=True, order='K', subok=False, │ │ ndmin=0) │ │ │ │ Create an array. │ │ │ │ Parameters │ │ ---------- │ │ object : array_like │ │ An array, any object exposing the array interface, an ob │ │ ject whose │ │ __array__ method returns an array, or any (nested) seque │ │ nce. │ │ dtype : data-type, optional │ └──────────────────────────────────────────────────────────────┘?
>>> ai32 = np.array([1,2,3,4],dtype = np.int32) >>> ai32 array([1, 2, 3, 4], dtype=int32) >>> ai32.shape (4,) >>> af = np.array([1,2,3,4],dtype = np.float) >>> af array([ 1., 2., 3., 4.]) >>> ac = np.array([1,2,3,4],dtype = np.complex) >>> ac array([ 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j]) >>> ac.shape (4,)>>> ai32.dtype
dtype('int32')
>>> af.dtype
dtype('float64')
>>> ac.dtype
dtype('complex128')
?
在上面的例子中傳遞給dtype參數的都是類型對象, 其中類型對象都是NumPy定義的數據類型. 當然內置的也有并且其效果和內置的相同.
在需要指定dtype參數的時候, 也可以傳遞一個字符串來表示元素的數值類型. NumPy中每個數值類型都有集中字符串的表達方式, 字符串和類型之間的對用關系都儲存在typeDict字典中,下面的程序獲得與float64類型對應的所有鍵值.
>>> [key for key, value in np.typeDict.items() if value is np.float64] [12, 'd', 'float_', 'float', 'double', 'Float64', 'f8', 'float64']好吧翻譯一下.
>>> for key,value in np.typeDict.items(): ... if value is np.float64: ... value,key ... ... ... (<class 'numpy.float64'>, 12) (<class 'numpy.float64'>, 'd') (<class 'numpy.float64'>, 'float_') (<class 'numpy.float64'>, 'float') (<class 'numpy.float64'>, 'double') (<class 'numpy.float64'>, 'Float64') (<class 'numpy.float64'>, 'f8') (<class 'numpy.float64'>, 'float64')完整的類型列表可以通過下面的語句獲得, 他講typeDict字典中的所有值轉化為一個集合,從而去除重復項. ( 重復項 值只有這么多, 但是一個值可以有很多個鍵. )
>>> set(np.typeDict.values()) {<class 'numpy.float128'>, <class 'numpy.uint64'>, <class 'numpy.int64'>, <class'numpy.str_'>, <class 'numpy.complex128'>, <class 'numpy.float64'>, <class 'num py.uint32'>, <class 'numpy.int32'>, <class 'numpy.bytes_'>, <class 'numpy.comple x64'>, <class 'numpy.float32'>, <class 'numpy.uint16'>, <class 'numpy.int16'>, < class 'numpy.bool_'>, <class 'numpy.timedelta64'>, <class 'numpy.float16'>, <cla ss 'numpy.uint8'>, <class 'numpy.int8'>, <class 'numpy.object_'>, <class 'numpy. datetime64'>, <class 'numpy.uint64'>, <class 'numpy.int64'>, <class 'numpy.void' >, <class 'numpy.complex256'>}上面顯示的數值類型與數組的dtype屬性是不同的對象. 通過dtype 對象的type屬性可以獲得與之對應的數值類型.
>>> c.dtype # 我的理解是這里的int64 指的是數組中的元素是 int64儲存的 dtype('int64') >>> c.dtype.type # 這里應該是數組本身是按照 numpy.int64的方式儲存的 , 不知道對不對, 如果不對我會回來修改的. <class 'numpy.int64'>通過NumPy的數值類型也可以創建數值對象, 下面創建一個16位的符號整數對象, 它與Python的整數對象不同的是,他的取值范圍有限, 因此計算200*200 會溢出,得到一個負數.
>>> a = np.int16(200) >>> a*a __console__:1: RuntimeWarning: overflow encountered in short_scalars -25536 >>> a+a 400另外值得指出的是, NumPy的數值對象的運算速度比Python的內置類型的運算速度慢的很多, 如果程序中需要大量的對單個數值進行計算, 應當避免使用NumPy的數值對象. 使用astype()方法可以對數組的元素類型進行轉換.
>>> t1 = np.array([1,2,3,4.0],dtype = np.float64) >>> t2 = np.array([1,2,3,4],dtype = np.complex) >>> t3 = t1.astype(np.int64) >>> t4 = t2.astype(np.complex256) >>> t1.dtype dtype('float64') >>> t2.dtype dtype('complex128') >>> t3.dtype dtype('int64') >>> t4.dtype dtype('complex256') >>> t4.dtype.type <class 'numpy.complex256'>?自動生成數組
前面的例子都是先創建一個Python的序列對象,然后通過array() 將其裝華為數組, 這樣做顯然效率不高 , 因此NumPy 提供了很多專門用于創建數組的函數 , 下面的每個函數都有一些關鍵字參數. 具體用法請查看函數說明.
arange() 類似于內置函數range() , 通過指定開始值, 終止值, 和步長來創建表示等差數列的一維數組, 注意所得到的結果不包含終止值.
>>> np.arange(0,1,0.1) array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])linspace 通過指定開始值和終止值以及步數,來創建一個數組. (line space : 線性等分 ?)?? 這個默認包含終止值.( 不然沒法弄了)
>>> np.linspace(0,8,9) array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.])當然我們可以通過指定endpoint的真假 來選擇是否包含終止值.
>>> np.linspace(0,8,9) array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.]) >>> np.linspace(0,8,9,endpoint = False) array([ 0. , 0.88888889, 1.77777778, 2.66666667, 3.55555556,4.44444444, 5.33333333, 6.22222222, 7.11111111]) >>> 0.88888888*9 7.99999992 >>> np.linspace(0,7,9) array([ 0. , 0.875, 1.75 , 2.625, 3.5 , 4.375, 5.25 , 6.125, 7. ])logspace()和linspace()類似, 不過他所創建的數組是等比數列.下面例子產生從100 到 102?,有5個元素的等比數列, 注意起始值0 代表100 終止值 2 代表 102?
>>> np.logspace(0,2,num = 4,endpoint = False,base = 4.0,dtype = np.float128) array([ 1.0, 2.0, 4.0, 8.0], dtype=float128)我用的bpython 在寫代碼的時候會有函數說明
np.logspace: (start, stop, num=50, endpoint=True, base=10.0, │ │ dtype=None) │ │ logspace │ │ Return numbers spaced evenly on a log scale. │ │ │ │ In linear space, the sequence starts at ``base ** start`` │ │ (`base` to the power of `start`) and ends with ``base ** sto │ │ p`` │ │ (see `endpoint` below). │ │ │ │ Parameters │ │ ---------- │ │ start : float │ │ ``base ** start`` is the starting value of the sequence. │ │ stop : float │ │ ``base ** stop`` is the final value of the sequence, unl │ │ ess `endpoint` │ │ is False. In that case, ``num + 1`` values are spaced o │ └──────────────────────────────────────────────────────────────┘? zeros(), ones(), empty()可以創建指定形狀的和類型的數組. 其中empty() 只分配數組所使用的內存, 不對數組進行初始化操作, 所以他的運行速度應該是最快的. 下面的程序位創建一個形狀為(2,3), 元素類型位整數的數組, 注意其中的元素沒有被初始化.
>>> np.empty((2,3),np.int) array([[ 0, 10914432, 10743840],[140263681062408, 140263663167672, 140263663165992]])
? 而zeros() 將數組初始化位0, ones()將數組元素初始化為1 . 下面創建一個長度位4, 而元素類型為整數的一維數組, 并且元素全部被初始化位0 :
>>> np.zeros(4,np.int) array([0, 0, 0, 0])full() 可以講元素初始化為指定的值:
>>> np.full((2,3),4,np.int64) array([[4, 4, 4],[4, 4, 4]])編譯器有代碼提示的同學可能很早就注意到了, zeros_like(), ones_like(), empty_like(), full_like() 等函數了. 這些函數創建與參數數組的形狀和類型相同的數組, 因此zeros_like(a) 和zeros(a.shape,a.dtype)的效果相同
>>> np.full(4,np.pi) array([ 3.14159265, 3.14159265, 3.14159265, 3.14159265]) >>> np.full((4,2),np.pi) array([[ 3.14159265, 3.14159265],[ 3.14159265, 3.14159265],[ 3.14159265, 3.14159265],[ 3.14159265, 3.14159265]])frombuffer(), fromstring(), fromfile() 等函數可以從字節序列, 或者文件創建數組. 下面以fromstring()為例子 , 展示他們的用法,? 很明顯這里值為-1 的一般都是自動計算.
>>> s = 'abcdefgh' >>> #python的字符串實際上是一個字節序列每個字符,占有一個字節. 因此如果從s中創建L編碼 >>> np.fromstring(s,np.int8,5) array([ 97, 98, 99, 100, 101], dtype=int8) >>> np.fromstring(s,np.int8,-1) array([ 97, 98, 99, 100, 101, 102, 103, 104], dtype=int8)存取元素
可以使用和列表相同的方式對數組的元素進行存取:
>>> a = np.arange(10) >>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])靈活靈活滴 .
>>> a[5] 5 >>> a[5:] array([5, 6, 7, 8, 9]) >>> a[5:6] array([5]) >>> a[5:8] array([5, 6, 7]) >>> a[5:-1] array([5, 6, 7, 8]) >>> a[-3:-1] array([7, 8]) >>> a[3:-1] array([3, 4, 5, 6, 7, 8])?
當使用證書列表對數組元素進行存取的時候,將使用列表中的每個元素作為下表, 使用列表作為下標得到的數組不和原始數組共享數據.
>>> x = np.arange(10,1,-1) >>> x array([10, 9, 8, 7, 6, 5, 4, 3, 2]) >>> a = x[[3,3,1,8]] >>> a array([7, 7, 9, 2]) >>> b = x[[3,3,-3,8]] >>> b array([7, 7, 4, 2])?
* 我們也可以通過上面的方式來進行批量賦值 .
>>> x[[0,1,2,3]] = 9,8,7,6 >>> x[[0,1,2,3]] array([9, 8, 7, 6]) >>> x array([9, 8, 7, 6, 6, 5, 4, 3, 2])?
? * 我們可以通過數組為下標的情況來獲得一個新的數組, 在一位數組中是這樣, 在多維中也是這樣.
array([10, 9, 8, 7, 6, 5, 4, 3, 2]) >>> x[np.array([[3,3,1,8],[3,3,-3,8]])] array([[7, 7, 9, 2],[7, 7, 4, 2]])?
* 當使用不二數組b 作為存取數組 x 中的元素時, 將獲得數組x 中與 數組b 中True對應的元素. 使用布爾數組作為下表獲得的數組不和原始數組共享數據內存,? 注意這種方式只對應與不二數組, 而不能使用布爾列表.
>>> x[np.array([True,False,True])] __console__:3: VisibleDeprecationWarning: boolean index did not match indexed ar ray along dimension 0; dimension is 9 but corresponding boolean dimension is 3 array([10, 8])?
* 當布爾數組的長度不夠的時候, 不夠的部分都當做False
*布爾數組一般不是手工產生的, 而是通過使用布爾運算的ufunc 函數產生的, 關于ufunc 函數請參照下一節課的介紹, 下面我們舉一個簡單的例子說明布爾數組下標的用法:
>>> np.random.randint(0,10,6) array([1, 9, 5, 0, 7, 2])?
>>> x[x>5]array([10,? 9,? 8,? 7,? 6])
>>> x
array([10,? 9,? 8,? 7,? 6,? 5,? 4,? 3,? 2])
?
多維數組
多維數組的存取和一維數組類似, 因為多維數組有多個軸, 所以他的下標需要用多少個值來表示, NumPy采用元祖作為數組的下標, 元祖中的每個元素和數組的每個軸對應.
為什么使用元祖作為下標.
Python的下標語法(用[] 存取序列中的元素)本身并不支持多維, 但是可以使用任何對象作為下標, 因此 NumPy使用元祖作為下標存取數組中的元素, 使用元祖可以很方便的表示多個軸的下標, 雖然在Python程序中經常使用圓括號將元祖中的元素括起來, 但其實元祖的使用語法,只需要逗號隔開元素即可, 例如 x,y = y,x 就是用元祖交換變量值的一個例子. 因此 a[1,2]和啊a[(1,2)] 完全相同, 都是使用元祖(1,2) 作為數組a 的下標.
`上面的二維數組是怎樣創建的? 其實他是一個加法表, 由縱向量(0,10,20,30,40,50)和橫向量(0,1,2,3,4,5)的元素想家而得的, 可以使用下面的語句創建他, 至于其原理, 將在后面的章節討論.
>>> a = np.arange(0,60,10).reshape(-1,1) + np.arange(0,5) >>> a array([[ 0, 1, 2, 3, 4],[10, 11, 12, 13, 14],[20, 21, 22, 23, 24],[30, 31, 32, 33, 34],[40, 41, 42, 43, 44],[50, 51, 52, 53, 54]])?
有的同學應該很好奇上面的圖中的是怎樣讓a[0,3:5] , a[4:,4:]等切片操作找到自己的位置的 ?? 其中的第0 個元素個 第 0 軸對應, 第一個元素和第一軸對應 , 然后就是普通的一維數組切片操作了, 在不同的維度中可以對應出來他們相交的點 , 相交的點就是 該切片操作表示的點.
?
如果下標元祖中只包含整數和切片, 那么得到的數組和原始數組共享數據 , 他是原數組的視圖 , 下面的例子中, 數組b是a的視圖 , 他們共享數據 , 因此修改b[0]的時候, 數組a中對應的元素也會被修改.
>>> b = a[0,3:5] >>> b array([3, 4]) >>> b[0] = 12312313 >>> b array([12312313, 4]) >>> a array([[ 0, 1, 2, 12312313, 4],[ 10, 11, 12, 13, 14],[ 20, 21, 22, 23, 24],[ 30, 31, 32, 33, 34],[ 40, 41, 42, 43, 44],[ 50, 51, 52, 53, 54]])?
?
切片對象(slice)
根據Python的語法,在[]中可以使用冒號隔開的兩個或者三個整數表示切片, 但是單獨生成切片對象時需要使用slice() 來創建. 他有三個參數值, 開始,結束,間隔. 當這些值需要省略時可以使用None, 例如
>>> a[:,2] array([ 2, 12, 22, 32, 42, 52]) >>> a[slice(None,None,None),2] array([ 2, 12, 22, 32, 42, 52])?
>>> a[slice(2,3),] array([[20, 21, 22, 23, 24]]) >>> b = a[slice(2,3),] >>> b array([[20, 21, 22, 23, 24]]) >>> a array([[ 0, 1, 2, 3, 4],[10, 11, 12, 13, 14],[20, 21, 22, 23, 24],[30, 31, 32, 33, 34],[40, 41, 42, 43, 44],[50, 51, 52, 53, 54]]) >>> b[0] array([20, 21, 22, 23, 24]) >>> b[0][0] = 123123 >>> b array([[123123, 21, 22, 23, 24]]) >>> a array([[ 0, 1, 2, 3, 4],[ 10, 11, 12, 13, 14],[123123, 21, 22, 23, 24],[ 30, 31, 32, 33, 34],[ 40, 41, 42, 43, 44],[ 50, 51, 52, 53, 54]])?
用Python的內置函數slice()創建下標實際上是比較麻煩的, 因此NumPy提供了一個s_對象來幫助我們創建數組下標, 請注意s_實際上是IndexExpression類的一個對象.(因為動不動就要填寫None)
>>> b = a[slice(2,,1),] File "<input>", line 1b = a[slice(2,,1),]^ SyntaxError: invalid syntax?
所以我們可以使用NumPy所提供的s_對象來幫助我們創建數組下標.
?
>>> a = np.arange(0,60,10).reshape(-1,1) + np.arange(0,5) >>> a array([[ 0, 1, 2, 3, 4],[10, 11, 12, 13, 14],[20, 21, 22, 23, 24],[30, 31, 32, 33, 34],[40, 41, 42, 43, 44],[50, 51, 52, 53, 54]]) >>> b = a[slice(None,None,2),slice(2,None,None)] >>> b array([[ 2, 3, 4],[22, 23, 24],[42, 43, 44]]) >>> c = a[np.s_[::2,2:]] >>> c array([[ 2, 3, 4],[22, 23, 24],[42, 43, 44]])?
s_為什么不是函數?
根據Python的語法, 只有在中括號[] 中才能使用以冒號隔開的切片語法, 如果s_ 是函數的話, 那么這些切片必須使用slice() 創建, 類似的對象還有mgrid 和 ogrid等, Python的下標語法實際上會調用getitem() 方法, 因此我們可以很容易實現s_對象的功能.
在a[(0,1,2,3),(1,2,3,4)] 中, 下標仍然是一個有兩個元素的元祖, 元祖中的每個元素都是一個整數元祖, 分別對應數組中的第0 軸和第 1 軸, 從兩個序列的對應位置取出兩個整數組成下標, 于是得到的結果是, a[0,1],a[1,2], a[2,3], a[3,4].
在a[3:,[0,2,5]]中, 第0軸的下標是一個切片對象, 它選取第三行之后的所有行, 第一軸的下標是整數列表, 它選取 第0,2,5列.
在a[mask,2]中, 第0軸的下標是一個布爾數組,他選取第0,2,5行,第一軸的下標是2.
>>> x = np.array([[0,1],[2,3]]) >>> y = np.array([[-1,-2],[-3,-4]]) >>> a[x,y] array([[ 5, 14],[23, 32]])?
結構數組
在C語言中我們可以通過struct 關鍵字定義結構類型, 結構中的字段占據連續的內存空間. 類型相同的兩個結構所占用的內存大小相同, 因此可以很容易的定義結構數組, 和C語言一樣, 在NumPy中也很容易堆這種結構數組進行操作, 只要NumPy中的結構定義和C語言中的結構定義相同, 就可以很方便的讀取C語言結構數組的二進制數據, 將其轉化為NumPy的結構數組.
假設 我們需要定義一個結構數組, 他的每個元素都有name , age 和 weight字段. 在NumPy中可以如下定義:
>>> persontype = np.dtype({ ... 'names':['name','age','weight'], ... 'formats':['S30','i','f']},align = True) >>> a = np.array([('zhang',32,75.5),('Wang',24,65.2)],dtype = persontype) >>> a[1] (b'Wang', 24, 65.19999695)?
我們先創建一個 persontype 的dtype對象, 他的參數是一個描述結構類型的各個字段的字典. 字典有兩個鍵, 'name'和'format'. 每個鍵對應的值都是一個列表. 'names' 定義結構中的每個字段的名稱, 而format 則定義為每個字段的類型, 我們這里使用類型字符串定義字符類型.
- 'S30' 長度位30個字節的字符串類型. 由于結構中的每個元素的大小必須固定, 因此需要指定字符串的長度.
- ?????? ' i '? 32位的整數類型相當于np.int32 .?
- ?????? ' f ' 32位的單精度浮點數.類型 相當于 np.float32
然后調用array() 以創建數組, 通過dtype 參數指定所創建的數組的元素類型為 persontype. 下面查看 a的數組類型
>>> a.dtype dtype({'names':['name','age','weight'], 'formats':['S30','<i4','<f4'], 'offsets' :[0,32,36], 'itemsize':40}, align=True)?
還可以用包含多個元祖的列表來描述結構的類型:
dtype([('name','|S30'),('age','<i4'),('weight','<f4')])?
其中形如 "字段名,類型描述"的元祖描述了結構中的每個字段, 類型字符串前面的'|','<',">"等字符表示字段值的字節順序:
- | : 忽視字節順序
- <: 低位字節在前, 即小端模式.
- >: 高位字節在前, 即大端模式.
- 結構數組的存儲方式和一般的數組相同, 通過下標能過取得其中的元素, 注意元素的值看上去像是數組, 實際上是結構.
>>> a[0]['name']
b'zhang'
>>> a[0]['age']
32
?
? a[0] 是一個結構元素, 他和數組a 共享內存數據, 因此可以通過修改它的字段來改變原始數組中對應元素的字段.
>>> c = a[1] >>> c (b'Wang', 24, 65.19999695) >>> c['age'] = 12312312312 >>> a[1] (b'Wang', -572589576, 65.19999695) # 溢出了?
?
>>> b = a['age'] >>> b array([ 32, -572589576], dtype=int32) >>> b[0] = 40 >>> b array([ 40, -572589576], dtype=int32) >>> a[0]['age'] 40?
?
? 我們可以通過a.tostring()或者a.tofile的方法,可以將數組a位2進制的方式轉換成字符串或寫入文件。
?
轉載于:https://www.cnblogs.com/A-FM/p/6517500.html
總結
以上是生活随笔為你收集整理的揭开Python科学计算的面纱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OSGI实战第一章
- 下一篇: Python练习-迭代器-模拟cat|g