人工智能之數據分析 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 存儲文本 無需字節交換

七、最佳實踐建議

  1. 讀取二進制數據時,始終明確指定字節序​(如 '>f4' 表示大端 float32)
  2. 不要對字符串數組做字節交換​(無意義且可能破壞編碼)
  3. 使用 arr.dtype.byteorder 檢查當前字節序
  4. 跨平台傳輸 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》