結(jié)構(gòu)化數(shù)據(jù)類型可以被認為是一定長度(結(jié)構(gòu)的itemsize)的字節(jié)序列,它被解釋為字段的集合。每個字段在結(jié)構(gòu)中都有一個名稱、一個數(shù)據(jù)類型和一個字節(jié)偏移量。字段的數(shù)據(jù)類型可以是任何 numpy 數(shù)據(jù)類型,包括其他結(jié)構(gòu)化數(shù)據(jù)類型,也可以是子數(shù)組數(shù)據(jù)類型,其行為類似于指定形狀的 ndarray。字段的偏移量是任意的,字段甚至可能重疊。這些偏移量通常由 numpy 自動確定,但也可以指定。
可以使用函數(shù)創(chuàng)建結(jié)構(gòu)化數(shù)據(jù)類型numpy.dtype
。有 4 種替代形式的規(guī)范,它們的靈活性和簡潔性各不相同。這些在數(shù)據(jù)類型對象參考頁面中有進一步的記錄?,總而言之,它們是:
(fieldname,?datatype,?shape)``fieldname``datatype``shape
>>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))])
dtype([('x', '<f4'), ('y', '<f4'), ('z', '<f4', (2, 2))])
如果fieldname
是空字符串''
,則該字段將被賦予表單的默認名稱f#
,其中#
是該字段的整數(shù)索引,從左側(cè)開始計數(shù):
>>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')])
dtype([('x', '<f4'), ('f1', '<i4'), ('z', '<i8')])
結(jié)構(gòu)內(nèi)字段的字節(jié)偏移量和總結(jié)構(gòu)項大小是自動確定的。
f0
,?f1
等等。
>>> np.dtype('i8, f4, S3')
dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])
>>> np.dtype('3int8, float32, (2, 3)float64')
dtype([('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])
>>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})
dtype([('col1', '<i4'), ('col2', '<f4')])
>>> np.dtype({'names': ['col1', 'col2'],
... 'formats': ['i4', 'f4'],
... 'offsets': [0, 4],
... 'itemsize': 12})
dtype({'names':['col1','col2'], 'formats':['<i4','<f4'], 'offsets':[0,4], 'itemsize':12})
可以選擇偏移以使字段重疊,盡管這意味著分配給一個字段可能會破壞任何重疊字段的數(shù)據(jù)。作為一個例外,numpy.object_
類型字段不能與其他字段重疊,因為存在破壞內(nèi)部對象指針然后取消引用它的風險。
可以將可選的 'aligned' 值設(shè)置為True
使自動偏移計算使用對齊的偏移(請參閱自動字節(jié)偏移和對齊),就好像 的 'align' 關(guān)鍵字參數(shù)numpy.dtype
已設(shè)置為 True。
可選的“titles”值應該是與“names”長度相同的標題列表,請參閱下面的字段標題。
>>> np.dtype({'col1': ('i1', 0), 'col2': ('f4', 1)})
dtype([('col1', 'i1'), ('col2', '<f4')])
不鼓勵這種形式,因為 Python 字典在 Python 3.6 之前的 Python 版本中不保留順序,并且結(jié)構(gòu)化 dtype 中字段的順序是有意義的??梢允褂?3 元組指定字段標題,請參見下文。
結(jié)構(gòu)化數(shù)據(jù)類型的字段名稱列表可以names
?在 dtype 對象的屬性中找到:
>>> d = np.dtype([('x', 'i8'), ('y', 'f4')])
>>> d.names
('x', 'y')
可以通過names
使用相同長度的字符串序列分配給屬性來修改字段名稱。
dtype 對象還有一個類似字典的屬性,fields
其鍵是字段名稱(和字段標題,見下文),其值是包含每個字段的 dtype 和字節(jié)偏移量的元組。
>>> d.fields
mappingproxy({'x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)})
對于非結(jié)構(gòu)化數(shù)組,thenames
和fields
attributes 都相等None
。測試dtype是否結(jié)構(gòu)化的推薦方法是使用if dt.names 不是 None而不是if dt.names,以考慮具有 0 個字段的 dtype。
如果可能,結(jié)構(gòu)化數(shù)據(jù)類型的字符串表示以“元組列表”形式顯示,否則 numpy 將退回使用更通用的字典形式。
Numpy 使用兩種方法之一來自動確定結(jié)構(gòu)化數(shù)據(jù)類型的字段字節(jié)偏移量和整體項大小,具體取決于是否?align=True
指定為 的關(guān)鍵字參數(shù)numpy.dtype
。
默認情況下 (?align=False
),numpy 會將字段打包在一起,以便每個字段從前一個字段結(jié)束的字節(jié)偏移量開始,并且這些字段在內(nèi)存中是連續(xù)的。
>>> def print_offsets(d):
... print("offsets:", [d.fields[name][1] for name in d.names])
... print("itemsize:", d.itemsize)
>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2'))
offsets: [0, 1, 2, 6, 7, 15]
itemsize: 17
如果align=True
設(shè)置,numpy 將以與許多 C 編譯器填充 C 結(jié)構(gòu)相同的方式填充結(jié)構(gòu)。在某些情況下,對齊結(jié)構(gòu)可以提高性能,但代價是增加了數(shù)據(jù)類型大小。在字段之間插入填充字節(jié),這樣每個字段的字節(jié)偏移量將是該字段對齊的倍數(shù),對于簡單數(shù)據(jù)類型,這通常等于字段的大?。ㄒ宰止?jié)為單位),請參閱PyArray_Descr.alignment
。該結(jié)構(gòu)還將添加尾隨填充,以便其項目大小是最大字段對齊的倍數(shù)。
>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True))
offsets: [0, 1, 4, 8, 16, 24]
itemsize: 32
請注意,盡管默認情況下幾乎所有現(xiàn)代 C 編譯器都以這種方式填充,但 C 結(jié)構(gòu)中的填充取決于 C 實現(xiàn),因此不能保證此內(nèi)存布局與 C 程序中相應結(jié)構(gòu)的內(nèi)存布局完全匹配??赡苄枰?numpy 端或 C 端做一些工作,以獲得精確的對應關(guān)系。
如果使用offsets
基于字典的 dtype 規(guī)范中的可選鍵指定偏移量,則設(shè)置align=True
將檢查每個字段的偏移量是否是其大小的倍數(shù),并且 itemsize 是最大字段大小的倍數(shù),如果不是,則引發(fā)異常。
如果結(jié)構(gòu)化數(shù)組的字段和itemsize的偏移量滿足對齊條件,則該數(shù)組將具有ALIGNED
?flag
集合。
便利函數(shù)numpy.lib.recfunctions.repack_fields
將對齊的 dtype 或數(shù)組轉(zhuǎn)換為壓縮類型,反之亦然。它采用 dtype 或結(jié)構(gòu)化 ndarray 作為參數(shù),并返回帶有重新打包的字段的副本,帶有或不帶有填充字節(jié)。
除了字段名稱之外,字段還可能有一個相關(guān)聯(lián)的title,一個備用名稱,有時用作字段的附加描述或別名。標題可用于索引數(shù)組,就像字段名稱一樣。
要在使用 dtype 規(guī)范的元組列表形式時添加標題,可以將字段名稱指定為兩個字符串的元組,而不是單個字符串,這將分別是字段的標題和字段名稱。例如:
>>> np.dtype([(('my title', 'name'), 'f4')])
dtype([(('my title', 'name'), '<f4')])
當使用第一種形式的基于字典的規(guī)范時,標題可以作為額外的'titles'
鍵提供,如上所述。當使用第二個(不鼓勵的)基于字典的規(guī)范時,可以通過提供一個 3 元素元組而不是通常的 2 元素元組來提供標題:(datatype,?offset,?title)
>>> np.dtype({'name': ('i4', 0, 'my title')})
dtype([(('my title', 'name'), '<i4')])
該dtype.fields
字典將包含標題作為鍵,如果使用任何頭銜。這實際上意味著具有標題的字段將在字段字典中出現(xiàn)兩次。這些字段的元組值還將具有第三個元素,即字段標題。正因為如此,并且因為names
屬性保留字段順序而fields
?屬性可能不保留,建議使用 dtype 的names
屬性遍歷 dtype 的字段,該屬性不會列出標題,如下所示:
>>> for name in d.names:
... print(d.fields[name][:2])
(dtype('int64'), 0)
(dtype('float32'), 8)
numpy.void
默認情況下,結(jié)構(gòu)化數(shù)據(jù)類型在 numpy 中實現(xiàn)為具有基本類型?,但可以使用數(shù)據(jù)類型對象中描述的 dtype 規(guī)范形式?將其他 numpy 類型解釋為結(jié)構(gòu)化類型。這里,是所需的底層 dtype,字段和標志將從?.?此 dtype 類似于 C 中的“聯(lián)合”。(base_dtype,?dtype)``base_dtype``dtype
更多建議: