当前位置: 首页 > news >正文

2025-10-08 Python 标准库 7——内置类型:二进制序列

文章目录

  • 1. bytes 对象
    • 1.1. bytes 的创建方式
      • 1.1.1. 字面值创建(b 前缀)
      • 1.1.2. 构造器创建(`bytes()`)
      • 1.1.3. 十六进制字符串转换(`bytes.fromhex()`)
    • 1.2. bytes 的核心特性与方法
      • 1.2.1. 序列特性(索引与切片)
      • 1.2.2. 十六进制转换(`bytes.hex()`)
      • 1.2.3. 解码为字符串(`bytes.decode()`)
  • 2. bytearray 对象
    • 2.1. bytearray 的创建方式
      • 2.1.1. 构造器创建(`bytearray()`)
      • 2.1.2. 十六进制字符串转换(`bytearray.fromhex()`)
    • 2.2. bytearray 的可变特性
    • 2.3. bytearray 的关键方法
  • 3. bytes 与 bytearray 的共同操作
    • 3.1. 通用序列方法
    • 3.2. 基于 ASCII 的方法
    • 3.3. printf 风格的二进制格式化
  • 4. memoryview 对象
    • 4.1. memoryview 的创建与基础特性
      • 4.1.1. 创建方式(`memoryview(obj)`)
      • 4.1.2. 序列特性(索引与切片)
    • 4.2. memoryview 的核心方法
      • 4.2.1. 数据转换(`tolist()`、`tobytes()`)
      • 4.2.2. 格式与形状转换(`cast()`)
      • 4.2.3. 内存释放(`release()` 与上下文管理)
    • 4.3. memoryview 关键属性
  • 5. 总结

参考文档:内置类型 — Python 3.13.7 文档

1. bytes 对象

bytes 是 Python 中处理二进制数据的不可变序列类型,每个元素是 0~255 范围内的整数(对应单个字节)。由于许多二进制协议基于 ASCII 设计,bytes 提供了部分与字符串(str)相似的方法,但仅适用于 ASCII 兼容场景;对于任意二进制数据,需避免盲目使用文本处理逻辑(防止数据损坏)。

1.1. bytes 的创建方式

bytes 对象可通过字面值、构造器或专用类方法创建,以下是常见方式及代码示例:

1.1.1. 字面值创建(b 前缀)

语法与字符串类似,但需添加 b 前缀,仅支持 ASCII 字符(非 ASCII 需用转义序列,如 \xXX)。支持单引号、双引号、三重引号,也可通过 r 前缀禁用转义。

# 单引号/双引号(支持嵌套)
b1 = b'hello "world"'
b2 = b'he said \'hi\''
print(b1)  # 输出:b'hello "world"'
print(b2)  # 输出:b'he said \'hi\''# 三重引号(多行二进制数据)
b3 = b'''line1
line2'''
print(b3)  # 输出:b'line1\nline2'(保留换行符)# 非 ASCII 需转义(\xXX 表示十六进制字节)
b4 = b'\xe4\xb8\xad\xe6\x96\x87'  # UTF-8 编码的“中文”
print(b4.decode('utf-8'))  # 输出:中文(解码为字符串)# r 前缀禁用转义
b5 = rb'C:\Users\xxx'  # \x 不被当作转义
print(b5)  # 输出:b'C:\\Users\\xxx'

1.1.2. 构造器创建(bytes()

构造器支持多种参数形式,灵活生成 bytes 对象:

  • bytes(n):创建长度为 n、以 0 填充的 bytes
  • bytes(iterable):通过 0~255 的整数可迭代对象创建;
  • bytes(obj):通过支持缓冲区协议的对象(如 bytearraymemoryview)复制创建。
# 1. 长度为 5、0 填充的 bytes
b1 = bytes(5)
print(b1)  # 输出:b'\x00\x00\x00\x00\x00'# 2. 通过整数可迭代对象(range(20) 需在 0~255 内)
b2 = bytes(range(5))  # 整数 0~4 对应字节 \x00~\x04
print(b2)  # 输出:b'\x00\x01\x02\x03\x04'# 3. 复制 bytearray 对象(缓冲区协议)
ba = bytearray(b'hello')
b3 = bytes(ba)
print(b3)  # 输出:b'hello'(与 ba 内容相同,但不可变)

1.1.3. 十六进制字符串转换(bytes.fromhex()

类方法 fromhex(string) 将十六进制字符串解码为 bytes,忽略字符串中的 ASCII 空白符(空格、制表符等)。

版本变更:Python 3.7+ 支持忽略所有 ASCII 空白符(此前仅忽略空格)。

# 基础用法:十六进制字符串转 bytes
b1 = bytes.fromhex('2E f0 F1 f2')  # 忽略空格,2E 对应 .,f0~f2 对应 \xf0~\xf2
print(b1)  # 输出:b'.\xf0\xf1\xf2'# 忽略多种空白符(3.7+ 支持)
b2 = bytes.fromhex('a1\tb2\nc3')  # 忽略制表符、换行符
print(b2)  # 输出:b'\xa1\xb2\xc3'

1.2. bytes 的核心特性与方法

1.2.1. 序列特性(索引与切片)

bytes 是序列类型,但索引返回整数(对应字节的数值,0~255),切片返回长度为 1 的 bytes 对象(与 str 索引返回字符不同)。

b = b'abc'
# 索引:返回整数(a 的 ASCII 码是 97)
print(b[0])       # 输出:97
# 切片:返回 bytes 对象
print(b[0:1])     # 输出:b'a'
# 反向索引
print(b[-1])      # 输出:99(c 的 ASCII 码)

1.2.2. 十六进制转换(bytes.hex()

实例方法 hex(sep=None, bytes_per_sep=1)bytes 转换为十六进制字符串,可选参数 sep 用于添加分隔符,bytes_per_sep 控制分隔符位置(正值从右数,负值从左数)。

版本变更:Python 3.8+ 支持 sepbytes_per_sep 参数。

b = b'\xf0\xf1\xf2\xf3'
# 基础用法:无分隔符
print(b.hex())  # 输出:'f0f1f2f3'# 添加分隔符(-)
print(b.hex('-'))  # 输出:'f0-f1-f2-f3'# 控制分隔符位置(每 2 个字节加 _)
print(b.hex('_', 2))  # 输出:'f0f1_f2f3'# 从左数每 3 个字节加空格(负值)
b2 = b'555544444c52'
print(b2.hex(' ', -4))  # 输出:'5555 4444 4c52'

1.2.3. 解码为字符串(bytes.decode()

bytes 按指定编码(默认 utf-8)解码为 strerrors 参数控制编码错误处理(如 strict 抛错、replace 替换为 )。

版本变更:Python 3.9+ 在开发/调试模式下检查 errors 参数有效性。

b = b'\xe4\xb8\xad\xe6\x96\x87'  # UTF-8 编码的“中文”
# 正常解码
print(b.decode('utf-8'))  # 输出:中文# 编码不匹配时处理错误
b_error = b'\xe4\xb8\xad\xe6'  # 不完整的 UTF-8 字节
print(b_error.decode('utf-8', errors='replace'))  # 输出:中�(替换错误字节)

2. bytearray 对象

bytearraybytes可变版本,支持修改元素值,但元素仍需是 0~255 的整数。bytearray 无专属字面值,需通过构造器创建。

2.1. bytearray 的创建方式

2.1.1. 构造器创建(bytearray()

构造器参数与 bytes 类似,但返回可变对象:

  • bytearray():空 bytearray
  • bytearray(n):长度为 n、0 填充的 bytearray
  • bytearray(iterable):通过 0~255 的整数可迭代对象创建;
  • bytearray(obj):通过缓冲区协议对象复制创建(如 bytesstrstr 需指定编码,或通过 bytearray(b'xxx'))。
# 1. 空 bytearray
ba1 = bytearray()
print(ba1)  # 输出:bytearray(b'')# 2. 长度为 3、0 填充
ba2 = bytearray(3)
print(ba2)  # 输出:bytearray(b'\x00\x00\x00')# 3. 整数可迭代对象
ba3 = bytearray(range(97, 100))  # 97~99 对应 a~c
print(ba3)  # 输出:bytearray(b'abc')# 4. 复制 bytes 对象
b = b'hello'
ba4 = bytearray(b)
print(ba4)  # 输出:bytearray(b'hello')

2.1.2. 十六进制字符串转换(bytearray.fromhex()

bytes.fromhex() 功能一致,将十六进制字符串解码为 bytearray,忽略 ASCII 空白符。

版本变更:Python 3.7+ 支持忽略所有 ASCII 空白符。

ba = bytearray.fromhex('a1 b2 c3')
print(ba)  # 输出:bytearray(b'\xa1\xb2\xc3')

2.2. bytearray 的可变特性

bytearray 支持修改单个元素或切片(元素需为 0~255 的整数,切片需为 bytesbytearray),但无法改变长度(需通过 appendextend 等方法调整长度)。

ba = bytearray(b'abc')
# 1. 修改单个元素(97 是 a,改为 65(A))
ba[0] = 65
print(ba)  # 输出:bytearray(b'Abc')# 2. 修改切片(替换为 bytes)
ba[1:3] = b'XY'
print(ba)  # 输出:bytearray(b'AXY')# 3. 调整长度(append 单个字节,extend 多个字节)
ba.append(90)  # 添加 Z(90 是 Z 的 ASCII 码)
ba.extend(b'12')  # 扩展 b'12'
print(ba)  # 输出:bytearray(b'AXYZ12')# 错误:元素超出 0~255
# ba[0] = 300  # 报错:ValueError: byte must be in range(0, 256)

2.3. bytearray 的关键方法

bytearray 继承了 bytes 的大部分方法,但需注意:多数方法并非原地操作,而是返回新对象(如 replacestrip),仅 appendextendpop 等是原地操作。

ba = bytearray(b'hello world')
# 1. replace(返回新 bytearray,原对象不变)
new_ba = ba.replace(b'world', b'python')
print(ba)       # 输出:bytearray(b'hello world')(原对象不变)
print(new_ba)   # 输出:bytearray(b'hello python')(新对象)# 2. strip(移除首尾空白,返回新对象)
ba2 = bytearray(b'   test   ')
stripped_ba = ba2.strip()
print(stripped_ba)  # 输出:bytearray(b'test')# 3. 原地操作(pop 移除最后一个元素)
ba3 = bytearray(b'abc')
ba3.pop()
print(ba3)  # 输出:bytearray(b'ab')

3. bytes 与 bytearray 的共同操作

bytesbytearray 均支持通用序列操作,部分方法还支持 bytes-like object(如 bytesbytearraymemoryview)作为参数;此外,二者还提供基于 ASCII 的文本操作(需注意仅适用于 ASCII 数据)。

3.1. 通用序列方法

以下方法适用于任意二进制数据,不依赖 ASCII 格式:

方法功能描述
count(sub[, start[, end]])统计 sub[start, end] 内非重叠出现次数,sub 可为 bytes-like 或 0~255 整数
find(sub[, start[, end]])查找 sub 的最小索引,未找到返回 -1,sub 支持 bytes-like 或整数
index(sub[, start[, end]])find,但未找到抛 ValueError
join(iterable)拼接 iterable 中的二进制序列,iterable 元素需为 bytes-like
partition(sep)sep 首次出现拆分,返回 (前, sep, 后) 三元组
rpartition(sep)sep 最后出现拆分,返回三元组
removeprefix(prefix)移除开头的 prefix(3.9+ 新增),返回新对象
removesuffix(suffix)移除结尾的 suffix(3.9+ 新增),返回新对象
# 1. count:统计子序列出现次数
b = b'spam spam spam'
print(b.count(b'spam'))        # 输出:3
print(b.count(115))            # 输出:3(115 是 's' 的 ASCII 码)# 2. find:查找子序列索引
print(b.find(b'spam', 5))      # 输出:6(从索引 5 开始找)# 3. join:拼接序列
parts = [b'hello', b' ', b'world']
print(b''.join(parts))         # 输出:b'hello world'# 4. removeprefix(3.9+)
b2 = b'TestHook'
print(b2.removeprefix(b'Test'))# 输出:b'Hook'

3.2. 基于 ASCII 的方法

以下方法假定数据为 ASCII 格式,仅处理 0~127 的字节,非 ASCII 字节保持不变,不适用于任意二进制数据(如图片、压缩文件):

方法功能描述
capitalize()首字节转为 ASCII 大写,其余转为小写
lower() / upper()所有 ASCII 字节转为小写/大写
swapcase()ASCII 字节大小写互换(swapcase().swapcase() == 原对象 恒成立)
isalnum()判断所有字节是否为 ASCII 字母/数字,且非空
isalpha()判断所有字节是否为 ASCII 字母,且非空
isdigit()判断所有字节是否为 ASCII 数字(0~9),且非空
# 1. capitalize:首字母大写
b = b'hello'
print(b.capitalize())  # 输出:b'Hello'# 2. upper:ASCII 大写(非 ASCII 字节不变)
b2 = b'hello \xe4\xb8\xad\xe6\x96\x87'  # 包含中文
print(b2.upper())      # 输出:b'HELLO \xe4\xb8\xad\xe6\x96\x87'(中文不变)# 3. isalnum:判断 ASCII 字母/数字
print(b'isalnum()')    # 输出:True(b'hello' 是 ASCII 字母)
print(b'hello123'.isalnum())  # 输出:True
print(b'hello!'.isalnum())    # 输出:False(包含 !)

3.3. printf 风格的二进制格式化

bytesbytearray 支持通过 % 运算符进行类似 C 语言 printf 的格式化,适用于兼容旧代码,推荐优先使用 f-字符串(需先解码为 str)。

核心转换符

转换符功能描述示例
%d/%i十进制整数b'%d' % 123b'123'
%x/%X十六进制整数(小写/大写)b'%x' % 255b'ff'
%b/%s二进制序列(bytes-likeb'%b' % b'abc'b'abc'
%c单个字节(整数或 bytesb'%c' % 97b'a'
%%输出 % 字符b'%%'b'%'
# 1. 基本格式化
print(b'Name: %b, Age: %d' % (b'Alice', 25))  # 输出:b'Name: Alice, Age: 25'# 2. 十六进制与整数
print(b'Hex: %x, Oct: %o' % (255, 8))  # 输出:b'Hex: ff, Oct: 10'# 3. 字典参数(映射键)
params = {b'name': b'Bob', b'age': 30}
print(b'Name: %(name)b, Age: %(age)d' % params)  # 输出:b'Name: Bob, Age: 30'

4. memoryview 对象

memoryview 是 Python 中高效访问二进制数据的工具,通过“缓冲区协议”直接访问对象内存(如 bytesbytearrayarray.array),无需复制数据,适合处理大二进制文件或高频数据操作。

4.1. memoryview 的创建与基础特性

4.1.1. 创建方式(memoryview(obj)

obj 需支持缓冲区协议,常见对象包括 bytesbytearrayarray.array 等。

# 1. 从 bytes 创建(只读,因 bytes 不可变)
b = b'abcdef'
mv1 = memoryview(b)
print(mv1)  # 输出:<memory at 0x0000021F7A8D4350># 2. 从 bytearray 创建(可写,因 bytearray 可变)
ba = bytearray(b'abcdef')
mv2 = memoryview(ba)
print(mv2.readonly)  # 输出:False(可写)

4.1.2. 序列特性(索引与切片)

memoryview 支持索引和切片,行为与 bytes 类似:

  • 索引返回整数(对应字节数值);
  • 切片返回memoryview 对象(不复制数据)。
mv = memoryview(b'abcdef')
# 1. 索引
print(mv[0])       # 输出:97(a 的 ASCII 码)
print(mv[-1])      # 输出:102(f 的 ASCII 码)# 2. 切片(返回子 memoryview,不复制)
sub_mv = mv[1:4]   # 对应 b'bcd'
print(sub_mv)      # 输出:<memory at 0x0000021F7A8D4410>
print(bytes(sub_mv))  # 输出:b'bcd'(转换为 bytes 查看内容)

4.2. memoryview 的核心方法

4.2.1. 数据转换(tolist()tobytes()

  • tolist():将内存数据转为 Python 列表(元素为整数,多维数据转为嵌套列表);
  • tobytes():将内存数据转为 bytes(复制数据,适合持久化或传输)。
# 1. 一维数据
mv1 = memoryview(b'abc')
print(mv1.tolist())  # 输出:[97, 98, 99]
print(mv1.tobytes()) # 输出:b'abc'# 2. 多维数据(需先通过 cast 调整形状,见 4.2.2)
import array
arr = array.array('l', [1, 2, 3, 4])  # 'l' 表示长整数(4 字节/元素)
mv2 = memoryview(arr).cast('l', shape=[2, 2])  # 转为 2x2 多维视图
print(mv2.tolist())  # 输出:[[1, 2], [3, 4]]

4.2.2. 格式与形状转换(cast()

cast(format, shape=None) 方法将 memoryview 转换为新格式或形状,不复制数据,仅调整内存解读方式:

  • format:目标格式(需为 struct 模块支持的单一元素格式,如 'B' 表示无符号字节、'l' 表示长整数);
  • shape:目标形状(默认为一维,如 [2, 3] 表示 2 行 3 列的二维数据)。
# 1. 格式转换:长整数(l)→ 无符号字节(B)
import array
arr = array.array('l', [0x12345678])  # 1 个长整数(4 字节)
mv = memoryview(arr)
# 转为无符号字节格式(每个长整数拆为 4 个字节)
mv_byte = mv.cast('B')
print(mv_byte.tolist())  # 输出:[120, 86, 52, 18](小端序:0x78→120, 0x56→86...)# 2. 形状转换:一维 → 二维
buf = b'12345678'  # 8 字节
mv2 = memoryview(buf).cast('B', shape=[2, 4])  # 2 行 4 列
print(mv2.tolist())  # 输出:[[49, 50, 51, 52], [53, 54, 55, 56]](1~8 的 ASCII 码)

4.2.3. 内存释放(release() 与上下文管理)

memoryview 会持有底层对象的引用,调用 release() 可手动释放内存(底层对象可恢复调整大小等能力);也可通过 with 语句自动释放。

# 1. 手动 release
ba = bytearray(b'abc')
mv = memoryview(ba)
mv.release()  # 释放内存
# 释放后操作报错
# print(mv[0])  # 报错:ValueError: operation forbidden on released memoryview object# 2. with 语句自动释放
with memoryview(bytearray(b'abc')) as mv:print(mv[0])  # 输出:97(上下文内正常使用)
# 上下文外已释放
# print(mv[0])  # 报错:ValueError: operation forbidden on released memoryview object

4.3. memoryview 关键属性

memoryview 提供多个只读属性,用于查看内存数据的元信息:

属性功能描述
nbytes内存数据总字节数(product(shape) * itemsize
readonly布尔值,表明内存是否只读(如 bytes 创建的 memoryviewTrue
format数据格式(struct 风格,如 'B''l'
itemsize单个元素的字节数(如 'l' 对应 4 或 8 字节,取决于系统)
shape数据形状(元组,如 (2, 4) 表示二维)
ndim数据维度(整数,如 2 表示二维)
import array
arr = array.array('l', [1, 2, 3, 4])  # 'l' 长整数,4 字节/元素
mv = memoryview(arr).cast('l', shape=[2, 2])print(mv.nbytes)    # 输出:16(2*2*4 字节)
print(mv.readonly)  # 输出:False(array 可修改)
print(mv.format)    # 输出:'l'
print(mv.itemsize)  # 输出:4(每个长整数 4 字节)
print(mv.shape)     # 输出:(2, 2)
print(mv.ndim)      # 输出:2

5. 总结

Python 二进制序列类型(bytesbytearraymemoryview)各有定位,适用场景不同:

  1. bytes:不可变二进制序列,适合存储固定二进制数据(如文件片段、网络数据包),支持哈希(可作为 dict 键);
  2. bytearray:可变二进制序列,适合动态修改二进制数据(如缓冲区、实时数据处理),但不支持哈希;
  3. memoryview:高效内存访问工具,无需复制数据,适合处理大二进制数据或高频操作(如音视频处理、科学计算)。

使用时需注意:

  • bytesbytearray 的方法区分“通用二进制操作”和“ASCII 专属操作”,避免用于非 ASCII 二进制数据;
  • memoryview 释放后不可再操作,推荐通过 with 语句管理生命周期;
  • 二进制格式化优先使用 f-字符串(需先解码为 str),仅兼容旧代码时使用 % 运算符。
http://www.dtcms.com/a/457891.html

相关文章:

  • 餐饮业建设网站意义音乐网站的设计
  • ip对网站作用网站开发后台做些什么
  • numpy -- 算术函数 reciprocal() 和 power() 简介
  • 面向中小型制造企业的SaaS版MES解决方案
  • 华为网站建设南通门户网站建设方案
  • Docker安装部署本地对象存储Minio和使用指南
  • 怎么看网站是什么程序营销网站开发选哪家
  • Spring Boot综合项目实战 - 西蒙购物网
  • 西安房产网站大全注册网址在哪里注册
  • 营口网站建设wordpress 添加付款
  • 深度学习和机器学习的区别,联邦学习和隐私计算的区别
  • 98.验证二叉搜索树(二叉树算法题)
  • linux信号(2)——从“暂停咖啡机”看SIGINT:用户与程序的“紧急停止按钮”
  • asp网站安全南京移动网站建设
  • leetcode hot100 中等难度 day05-刷题
  • 企业网站每年的费用wordpress目录魔板
  • 做一个小公司网站多少钱网站备案归属地
  • Access调用Azure翻译:轻松实现系统多语言切换
  • R语言从入门到精通Day5之【数据输入】
  • 网站开发挣不挣钱南通网站建设知识
  • 仿手机底部导航栏制作
  • 二维码生成的技术原理与全场景实践
  • 做网站 嵌入支付wordpress优化攻略
  • Chromium Embedded Framework (CEF)的构建及运行
  • 批量替换yaml文件url字段
  • “软件维护” 分 4 类?用 “奶茶店售后” 讲透更正 / 适应性 / 完善性维护
  • 恋爱ppt模板免费下载网站网站建设项目风险管理的主要内容
  • 网站主机选择98建筑人才网
  • Windows中在QTCreator中调试,提示缺少debug information files问题的解决
  • 做宠物店网站的素材seo一级域名和二级域名