人工智能之數據分析 numpy
第十一章 字符串與字節交換
(文章目錄)
前言
在 NumPy 中,字符串數組 和 字節序(Endianness)交換 是兩個重要但常被忽視的主題。下面分別詳細講解,並説明它們的聯繫與應用場景。
一、NumPy 中的字符串數組
NumPy 支持兩種主要的字符串類型:
| 類型 | 描述 | 創建方式 |
|---|---|---|
'U'(Unicode 字符串) |
固定長度 Unicode 字符串(Python 3 默認) | dtype='U10' 表示最多 10 個字符 |
'S'(字節字符串) |
固定長度 ASCII/字節字符串(類似 Python 的 bytes) |
dtype='S10' 表示 10 字節 |
⚠️ 注意:NumPy 字符串是 固定長度 的!超長會被截斷,不足會用空字符填充。
1. 創建字符串數組
import numpy as np
# Unicode 字符串 (推薦)
arr_u = np.array(['apple', 'banana', 'cherry'], dtype='U10')
print(arr_u.dtype) # <U10 → 小端 Unicode,最大 10 字符
# 字節字符串
arr_s = np.array([b'hello', b'world'], dtype='S8')
print(arr_s.dtype) # |S8 → 8 字節 ASCII 字符串
2. 固定長度行為示例
a = np.array(['Python', 'NumPy'], dtype='U5')
print(a) # ['Pytho' 'NumPy'] → 'Python' 被截斷為 5 字符!
3. 字符串操作(向量化)
NumPy 提供 np.char 模塊進行向量化字符串操作:
names = np.array(['Alice', 'Bob', 'Charlie'], dtype='U10')
# 轉大寫
print(np.char.upper(names)) # ['ALICE' 'BOB' 'CHARLIE']
# 替換
print(np.char.replace(names, 'a', 'A')) # ['Alice' 'Bob' 'ChAr lie'](注意大小寫)
# 拼接
print(np.char.add(names, '_user')) # ['Alice_user' 'Bob_user' 'Charlie_user']
✅ 優勢:比 Python 循環快得多(尤其大數據量)
二、字節序(Endianness)與字節交換
1. 什麼是字節序?
- **小端(Little-endian,
<)**:低位字節在前(x86 CPU 默認) - **大端(Big-endian,
>)**:高位字節在前(網絡協議、某些嵌入式系統)
例如:整數 0x12345678 在內存中的存儲:
| 字節序 | 內存順序(低地址 → 高地址) |
|---|---|
| 小端 | 78 56 34 12 |
| 大端 | 12 34 56 78 |
2. NumPy 中的字節序標識
NumPy dtype 的字符串表示包含字節序前綴:
a = np.array([1, 2, 3], dtype='<i4') # 小端 32 位整數
b = np.array([1, 2, 3], dtype='>i4') # 大端 32 位整數
print(a.dtype.str) # '<i4'
print(b.dtype.str) # '>i4'
<:小端(little-endian)>:大端(big-endian)=:本機字節序(默認)|:不適用(如字符串、布爾值)
3. 為什麼要字節交換?
- 跨平台數據交換:從大端機器讀取的數據在小端機器上需轉換
- 讀取二進制文件:如科學儀器、網絡抓包、舊系統導出的數據
- GPU/加速器要求特定字節序
三、NumPy 中的字節交換操作
方法 1:.byteswap() —— 返回新數組(可選 in-place)
a = np.array([1, 256, 65536], dtype='=i4') # 本機字節序
print(a.view('uint8')) # 查看原始字節(假設小端): [1,0,0,0, 0,1,0,0, ...]
# 字節交換(返回副本)
b = a.byteswap()
print(b.view('uint8')) # [0,0,0,1, 1,0,0,0, ...] → 變成大端字節序
# in-place 交換(修改原數組)
a.byteswap(inplace=True)
🔍 注意:
byteswap()只交換字節順序,不改變 dtype 的字節序標記!
方法 2:.newbyteorder() —— 創建新 dtype 視圖(推薦!)
a = np.array([1, 2, 3], dtype='<i4') # 小端
# 創建一個“認為自己是大端”的視圖(不復制數據!)
b = a.newbyteorder('>') # 或 '>'
print(b.dtype) # >i4
print(b[0]) # 值會按大端解釋!可能變成一個奇怪的大數
# 如果你有一個大端數據文件,但當前系統是小端:
# 先用本機序讀入,再用 newbyteorder 標記為大端,最後 byteswap 糾正值
方法 3:正確讀取外部大端數據(標準流程)
# 假設你從文件讀取了大端整數(但 NumPy 默認按本機序解釋)
raw_data = np.frombuffer(file_content, dtype='>i4') # 直接指定 dtype 為大端!
# 或者:先按本機讀,再轉換
data_native = np.frombuffer(file_content, dtype='=i4')
data_correct = data_native.byteswap().newbyteorder() # 交換字節 + 更新 dtype 標記
四、字符串數組與字節序的關係
- **字符串類型(
'U','S')的字節序標記是'|'**,表示“無字節序”(因為字符是逐字節存儲的,無需考慮多字節整數那樣的字節順序)。
s = np.array(['hello'], dtype='U5')
print(s.dtype.byteorder) # '|' → 不適用
- **但 Unicode 字符本身可能涉及編碼(如 UTF-32 有字節序)**,不過 NumPy 內部統一處理為 UCS-4(固定 4 字節/字符),並使用本機字節序存儲。
✅ 結論:對字符串數組通常不需要手動字節交換,除非你在處理原始二進制編碼數據。
五、實戰示例:讀取二進制文件(含字節序)
假設有一個二進制文件 data.bin,包含 3 個大端 32 位整數:[0x00000001, 0x00000100, 0x00010000]
# 正確方式:直接指定 dtype 為大端
with open('data.bin', 'rb') as f:
data = np.frombuffer(f.read(), dtype='>i4')
print(data) # [1, 256, 65536] → 正確!
# 錯誤方式(本機小端解釋大端數據):
data_wrong = np.frombuffer(f.read(), dtype='<i4')
print(data_wrong) # [16777216, 65536, 256] → 完全錯誤!
六、總結速查表
| 操作 | 用途 | 是否複製數據 |
|---|---|---|
arr.byteswap() |
交換每個元素的字節順序 | 默認返回副本,inplace=True 則修改原數組 |
arr.newbyteorder('>') |
創建新 dtype 視圖(標記字節序) | ❌(視圖,不復制) |
np.frombuffer(..., dtype='>i4') |
讀取外部大端數據 | 取決於底層 buffer |
字符串數組(U/S) |
存儲文本 | 無需字節交換 |
七、最佳實踐建議
- 讀取二進制數據時,始終明確指定字節序(如
'>f4'表示大端 float32) - 不要對字符串數組做字節交換(無意義且可能破壞編碼)
- 使用
arr.dtype.byteorder檢查當前字節序 - 跨平台傳輸 NumPy 數組時,優先使用
.npy格式(自動處理字節序)
掌握 NumPy 的字符串數組和字節序機制,能讓你安全高效地處理科學計算、嵌入式數據、網絡協議等真實場景中的二進制與文本數據!💾🌐
後續
本文主要講述了numpy數組副本和視圖。python過渡項目部分代碼已經上傳至gitee,後續會逐步更新,主要受時間原因限制,當然自己也可以克隆到本地學習拓展。
資料關注
公眾號:咚咚王 gitee:https://gitee.com/wy18585051844/ai_learning
《Python編程:從入門到實踐》 《利用Python進行數據分析》 《算法導論中文第三版》 《概率論與數理統計(第四版) (盛驟) 》 《程序員的數學》 《線性代數應該這樣學第3版》 《微積分和數學分析引論》 《(西瓜書)周志華-機器學習》 《TensorFlow機器學習實戰指南》 《Sklearn與TensorFlow機器學習實用指南》 《模式識別(第四版)》 《深度學習 deep learning》伊恩·古德費洛著 花書 《Python深度學習第二版(中文版)【純文本】 (登封大數據 (Francois Choliet)) (Z-Library)》 《深入淺出神經網絡與深度學習+(邁克爾·尼爾森(Michael+Nielsen)》 《自然語言處理綜論 第2版》 《Natural-Language-Processing-with-PyTorch》 《計算機視覺-算法與應用(中文版)》 《Learning OpenCV 4》 《AIGC:智能創作時代》杜雨+&+張孜銘 《AIGC原理與實踐:零基礎學大語言模型、擴散模型和多模態模型》 《從零構建大語言模型(中文版)》 《實戰AI大模型》 《AI 3.0》