Python bytearray 与 bytes 的真实区别

12次阅读

bytes不可变而bytearray可变:前者修改会新建对象,后者支持原地增删改;bytes适用于只读场景如网络传输,bytearray适合动态编辑如协议组装;二者可相互转换但需显式调用。

Python bytearray 与 bytes 的真实区别

bytearray 和 bytes 最核心的区别在于:bytes 是不可变的,bytearray 是可变的。这意味着你不能修改 bytes 对象的内容,但可以对 bytearray 做增删改操作。

内存行为与可变性差异

bytes 创建后,任何试图修改其单个字节的操作(比如 b[0] = 65)都会抛出 TypeError。它像 tuple 或 str 一样,每次“修改”实际是新建对象。而 bytearray 支持原地修改,例如 ba[0] = 65 直接改变首字节,不产生新对象,适合频繁编辑二进制数据的场景。

  • bytes 常用于网络传输、文件读取结果、哈希输入等只读用途
  • bytearray 更适合协议组装、加密中间处理、缓冲区填充等需要动态调整的场合
  • 两者都支持索引、切片in 判断、常见方法如 find()replace()(注意:bytes 的 replace() 返回新 bytes,bytearray 的则就地修改并返回自身)

创建方式与类型转换

bytes 可通过字面量(b'abc')、encode()、或 bytes() 构造函数生成;bytearray 必须显式调用 bytearray(),不支持字面量语法。它们之间能互相转换,但需明确意图:

  • bytearray(b'hello') → 新建可变副本
  • bytes(bytearray(b'hello')) → 转为不可变视图(不拷贝底层数据,但返回新 bytes 对象)
  • 直接赋值(如 ba = b'abc')不会自动转成 bytearray,类型不会隐式升级

性能与使用边界

虽然 bytearray 支持修改,但它不是万能加速器。小规模操作(如改一两个字节)几乎看不出差别;但大量追加(extend())、插入(insert())或删除(del)时,bytearray 比反复拼接 bytes 快得多——后者每次拼接都触发内存分配和复制。

立即学习Python免费学习笔记(深入)”;

  • 避免用 += 拼接大量 bytes:b += b'x01'循环中是 O(n²) 时间复杂度
  • 同等情况优先用 bytearray.append() 或 extend():平均 O(1) 摊还时间
  • 若最终要传给只接受 bytes 的 API(如 socket.send()),再一次性转回:sock.send(bytes(ba))

共享底层缓冲区的注意事项

bytearray 和 bytes 都可基于 memoryview 观察同一块内存,但修改 bytearray 会影响所有引用它的 memoryview;而 bytes 的 memoryview 是只读的。这点在线程或零拷贝场景中容易踩坑:

  • ba = bytearray(b'abc'); mv = memoryview(ba) → 修改 ba[0] 同时改变 mv[0]
  • b = b'abc'; mv = memoryview(b) → 尝试 mv[0] = 65 报错
  • 不要假设 bytes 切片一定独立:b[1:3] 通常共享内存(Cpython 实现细节),但这是内部优化,不应依赖
text=ZqhQzanResources