1. 程式人生 > >python利用numpy實現結構體

python利用numpy實現結構體

在C語言中我們可以通過struct關鍵字定義結構型別,結構中的欄位佔據連續的記憶體空間,每個結構體佔用的記憶體大小都相同,因此可以很容易地定義結構陣列。和C語言一樣,在NumPy中也很容易對這種結構陣列進行操作。只要NumPy中的結構定義和C語言中的定義相同,NumPy就可以很方便地讀取C語言的結構陣列的二進位制資料,轉換為NumPy的結構陣列。

假設我們需要定義一個結構陣列,它的每個元素都有name, age和weight欄位。在NumPy中可以如下定義:

import numpy as np
persontype = np.dtype({
    'names':['name', 'age'
, 'weight'], 'formats':['S32','i', 'f']}) a = np.array([("Zhang",32,75.5),("Wang",24,65.2)], dtype=persontype)

我們先建立一個dtype物件persontype,通過其字典引數描述結構型別的各個欄位。字典有兩個關鍵字:names,formats。每個關鍵字對應的值都是一個列表。names定義結構中的每個欄位名,而formats則定義每個欄位的型別:

  • S32 : 32個位元組的字串型別,由於結構中的每個元素的大小必須固定,因此需要指定字串的長度
  • i : 32bit的整數型別,相當於np.int32
  • f : 32bit的單精度浮點數型別,相當於np.float32

然後我們呼叫array函式建立陣列,通過關鍵字引數 dtype=persontype, 指定所建立的陣列的元素型別為結構persontype。執行上面程式之後,我們可以在IPython中執行如下的語句檢視陣列a的元素型別

>>> a.dtype
dtype([('name', '|S32'), ('age', '<i4'), ('weight', '<f4')])

這裡我們看到了另外一種描述結構型別的方法: 一個包含多個組元的列表,其中形如 (欄位名, 型別描述) 的組元描述了結構中的每個欄位。型別描述前面為我們添加了 '|', '<' 等字元,這些字元用來描述欄位值的位元組順序:

  • | : 忽視位元組順序
  • < : 低位位元組在前
  • > : 高位位元組在前

結構陣列的存取方式和一般陣列相同,通過下標能夠取得其中的元素,注意元素的值看上去像是組元,實際上它是一個結構:

>>> a[0]
('Zhang', 32, 75.5)
>>> a[0].dtype
dtype([('name', '|S32'), ('age', '<i4'), ('weight', '<f4')])

a[0]是一個結構元素,它和陣列a共享記憶體資料,因此可以通過修改它的欄位,改變原始陣列中的對應欄位:

>>> c = a[1]
>>> c["name"] = "Li"
>>> a[1]["name"]
"Li"

結構像字典一樣可以通過字串下標獲取其對應的欄位值:

>>> a[0]["name"]
'Zhang'

我們不但可以獲得結構元素的某個欄位,還可以直接獲得結構陣列的欄位,它返回的是原始陣列的檢視,因此可以通過修改b[0]改變a[0]["age"]:

>>> b=a[:]["age"] # 或者a["age"]
>>> b
array([32, 24])
>>> b[0] = 40
>>> a[0]["age"]
40

通過呼叫a.tostring或者a.tofile方法,可以直接輸出陣列a的二進位制形式:

>>> a.tofile("test.bin")

利用下面的C語言程式可以將test.bin檔案中的資料讀取出來。

記憶體對齊

C語言的結構體為了記憶體定址方便,會自動的新增一些填充用的位元組,這叫做記憶體對齊。例如如果把下面的name[32]改為name[30]的話,由於記憶體對齊問題,在name和age中間會填補兩個位元組,最終的結構體大小不會改變。因此如果numpy中的所配置的記憶體大小不符合C語言的對齊規範的話,將會出現資料錯位。為了解決這個問題,在建立dtype物件時,可以傳遞引數align=True,這樣numpy的結構陣列的記憶體對齊和C語言的結構體就一致了。

#include <stdio.h>

struct person
{
    char name[32];
    int age;
    float weight;
};

struct person p[2];

void main ()
{
    FILE *fp;
    int i;
    fp=fopen("test.bin","rb");
    fread(p, sizeof(struct person), 2, fp);
    fclose(fp);
    for(i=0;i<2;i++)
        printf("%s %d %f\n", p[i].name, p[i].age, p[i].weight);
    getchar();
}

結構型別中可以包括其它的結構型別,下面的語句建立一個有一個欄位f1的結構,f1的值是另外一個結構,它有欄位f2,其型別為16bit整數。

>>> np.dtype([('f1', [('f2', np.int16)])])
dtype([('f1', [('f2', '<i2')])])

當某個欄位型別為陣列時,用組元的第三個引數表示,下面描述的f1欄位是一個shape為(2,3)的雙精度浮點陣列:

>>> np.dtype([('f0', 'i4'), ('f1', 'f8', (2, 3))])
dtype([('f0', '<i4'), ('f1', '<f8', (2, 3))])

用下面的字典引數也可以定義結構型別,字典的關鍵字為結構中欄位名,值為欄位的型別描述,但是由於字典的關鍵字是沒有順序的,因此欄位的順序需要在型別描述中給出,型別描述是一個組元,它的第二個值給出欄位的位元組為單位的偏移量,例如age欄位的偏移量為25個位元組:

>>> np.dtype({'surname':('S25',0),'age':(np.uint8,25)})

dtype([('surname', '|S25'), ('age', '|u1')])

轉載的,網址是http://old.sebug.net/paper/books/scipydoc/numpy_intro.html

相關推薦

python利用numpy實現結構

在C語言中我們可以通過struct關鍵字定義結構型別,結構中的欄位佔據連續的記憶體空間,每個結構體佔用的記憶體大小都相同,因此可以很容易地定義結構陣列。和C語言一樣,在NumPy中也很容易對這種結構陣列進行操作。只要NumPy中的結構定義和C語言中的定義相同,NumPy就

Python 利用socket 實現 ssh 跳轉

socket python squid 1.場景描述:主機A主機B主機C10.13.170.76172.28.117.156(squid)10.95.113.131 主機A---->主機B(80)--->主機C(22), A通過B的80訪問主機C131 2.Python代碼;im

golang-利用反射給結構賦值

cnblogs logs val valueof blog eof 成員 str byname 由於想給一個結構體的部分成員賦值,但是有不知道具體名字,故將tag的json名字作為索引,按照json名字來一一賦值 //將結構體裏的成員按照json名字來賦值 func

c語言 利用聯合和結構將IP地址進行列印

       在每一個計算機中都有他自己的IP地址,而IP地址是如何在計算機中儲存的是一直以來我們都不知道的。        在計算機中,IP地址的存放是由10進位制陣列組成的,而計算機將IP地址呈現給我們時則是以點

golang利用反射設定結構變數的值

如果需要動態設定struct變數field的情況下, 可以利用reflect來完成. 程式碼如下: package main import ( "fmt" "reflect" ) // 定義結構

python利用paramiko實現ssh連線及遠端執行命令

python3.6, windows下 1,安裝paramiko模組 依賴cryptography:使用命令easy_install安裝該模組時,如果報錯“...microsoft visual c++ 14.0 is required.”, 可以下載.whl檔案,使用命令pip instal

python-利用生成器實現併發

1.建立一個生成器: next和send都可以使生成器物件輸出。 區別在send可以傳值。 def create_num(all_num): print('-----1-------') a, b = 0, 1 current_num = 0 while

stack的陣列實現(結構封裝版)

//棧的陣列實現(結構體封裝版) //-->棧被定義為結構體指標,具體陣列也被定義為指標,棧動態新建 #define MAXSIZE 100 struct node { int capa

分別用OpenCV-PythonNumpy實現傅立葉變換和逆傅立葉變換

Numpy實現 fft = np.fft.fft2(img) 將空間域轉化為頻率域 OpenCV實現 dft = cv2.dft(np.float32(img),flag=cv2.DFT_COMPLEX_OUTPUT) 這個函式與np.fft.fft2(img)實現相同的功能,但要注意先

Python利用scapy實現ARP欺騙

一、實驗原理。         本次用程式碼實現的是ARP閘道器欺騙,通過傳送錯誤的閘道器對映關係導致區域網內其他主機無法正常路由。使用scapy中scapy.all模組的ARP、sendp、Ether等函式完成包的封裝與傳

Java中如何實現結構?如何對結構進行排序?

***今天在做老師佈置的程式設計題時,遇到了本題。感覺這道題如果用C++來解決的話,用結構體比較好吧!哈哈哈,可能還有其他的好方法,但我目前想到的是用結構體來解決比較合理。Java中有結構體嗎?如果有,它是如何實現的呢?例項和解決方法見下。(前面是Java中有關結構體的一些知

pythonnumpy實現神經網路 實現 手寫數字識別

首先是讀取檔案,train-images-idx3-ubyte等四個檔案是mnist資料集裡的資料。放在MNIST資料夾裡。MNIST資料夾和這個.py檔案放在同一個資料夾裡。 import numpy as np import struct train_images

Python利用APScheduler實現定時任務框架

APScheduler是一款功能非常強大的定時任務框架。利用APScheduler框架我們可以很方便實現一個基於Python的定時任務系統 1,安裝 pip install apscheduler 2,簡單呼叫(一次性呼叫任務) from apscheduler.sc

在Golang裡如何實現結構成員指標到結構自身指標的轉換

在C語言中有一個經典的巨集定義,可以將結構體struct內部的某個成員的指標轉化為結構體自身的指標。下面是一個例子,通過FIELD_OFFSET巨集計算結構體內一個欄位的偏移,函式getT可以從一個F*的指標獲得對應的T*物件。 struct F { int c; int d; }

Python利用heapq實現一個優先順序佇列

實現一個優先順序佇列,每次pop的元素要是優先順序高的元素,由於heapq.heapify(list)預設構建一個小頂堆,因此要將priority變為相反數再push,程式碼如下: import he

python-利用senleium實現定時重啟路由器

color 重啟 pin start exception starting datetime man import from selenium import webdriver import time #from datetime import * #import sen

PythonNumpy實現深度學習常用的函式

目錄 常用的啟用函式 我們常用的啟用函式有sigmoid,tanh,ReLU這三個函式,我們都來學習學習吧。 sigmoid函式 在深度學習中,我們經常會使用到sigmoid函式作為我們的啟用函式,特別是在二分類上,sigmoid函式是比較

初學資料分析(一)【利用numpy實現矩陣標準化】

大資料分析中許多情況下需要用到矩陣標準化(使該矩陣每一列的平均值為0,標準差為1)Here is the formula: (X-mean())/std()以上運算是按列進行的,因為通常大資料分析中的矩陣X N*M,其中每一行代表一個數據,而列代表不同的性質,既是N個數據,每

Python:類與結構

Python的類提供了面向物件程式設計的所有標準特性:類繼承機制允許有多個基類,一個派生類可以覆蓋基類中的任何方法,一個方法可以使用相同的名字呼叫基類中的方法。 1. Python的域(scopes)和名稱空間(namespaces) 名稱空間是名字和物

Java用類實現結構的功能

我們都知道C/C++裡面的結構體在儲存資料的時候很方便,但是在Java中沒有Struct,但是我們可以用類來實現Struct的功能 與Struct宣告功能一樣的類的定義: public  class platform {     private int x;//平臺左端的位