第十一章 字符串与字节交换
在 NumPy 中, 字符串数组 和 字节序(Endianness)交换 是两个重要但常被忽视的主题。下面分别详细讲解,并说明它们的联系与应用场景。
NumPy 支持两种主要的字符串类型:
| 类型 | 描述 | 创建方式 |
| --------------------------------------- | -------------------------------------------------------- | ------------------------------------- |
|
'U'(Unicode 字符串) | 固定长度 Unicode 字符串(Python 3 默认) |
dtype='U10' 表示最多 10 个字符 |
|
'S'(字节字符串) | 固定长度 ASCII/字节字符串(类似 Python 的
bytes) |
dtype='S10' 表示 10 字节 |
⚠️ 注意:NumPy 字符串是 固定长度 的!超长会被截断,不足会用空字符填充。
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 字符串
a = np.array(['Python', 'NumPy'], dtype='U5') print(a) # ['Pytho' 'NumPy'] → 'Python' 被截断为 5 字符!
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 循环快得多(尤其大数据量)
<):低位字节在前(x86 CPU 默认)>):高位字节在前(网络协议、某些嵌入式系统)例如:整数
0x12345678 在内存中的存储:
| 字节序 | 内存顺序(低地址 → 高地址) |
|---|---|
| 小端 |
78 56 34 12 |
| 大端 |
12 34 56 78 |
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)=:本机字节序(默认)|:不适用(如字符串、布尔值).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 的字节序标记!
.newbyteorder() —— 创建新 dtype 视图(推荐!)a = np.array([1, 2, 3], dtype='<i4') # 小端
# 创建一个“认为自己是大端”的视图(不复制数据!)
b = a.newbyteorder('>') # 或 '>'
print(b.dtype) # >i4
print(b[0]) # 值会按大端解释!可能变成一个奇怪的大数
# 如果你有一个大端数据文件,但当前系统是小端:
# 先用本机序读入,再用 newbyteorder 标记为大端,最后 byteswap 纠正值
# 假设你从文件读取了大端整数(但 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) # '|' → 不适用
✅ 结论: 对字符串数组通常不需要手动字节交换,除非你在处理原始二进制编码数据。
假设有一个二进制文件
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 检查当前字节序.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》
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048224/viewspace-3103062/ ,如需转载,请注明出处,否则将追究法律责任。