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

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 实现细节),但这是内部优化,不应依赖










