← 返回题目列表

Python 中 str、bytes、bytearray 有什么区别?

高频 中等 第 13 / 21 题 更新于 2026/07/25
Pythonstrbytesbytearray编码

简化版

str 表示 Unicode 文本,bytes 表示不可变的字节序列,bytearray 表示可变字节序列。文本和字节之间需要通过编码转换:str.encode() 把文本编码成 bytes,bytes.decode() 把 bytes 解码成文本。

详细版

基本区别:

类型含义是否可变典型场景
str文本字符串不可变业务文本、JSON 字段、日志文本
bytes字节序列不可变网络传输、文件二进制、加密摘要
bytearray字节序列可变需要原地修改二进制数据

编码和解码:

s = "你好"
b = s.encode("utf-8")
print(b)  # b'\xe4\xbd\xa0\xe5\xa5\xbd'

text = b.decode("utf-8")
print(text)  # 你好

常见错误:

# "你好" + b"world"  # TypeError

strbytes 不能直接拼接,必须明确编码或解码。

完整版教学

一、先分清三层:字符、编码、字节

这道题的核心不是背 strbytesbytearray 三个定义,而是分清“文本含义”和“底层字节”不是一回事。str 站在字符层,表示人能理解的文本;bytes 站在字节层,表示网络、磁盘、加密算法看到的原始数据;编码就是把字符映射成字节的规则。

文本字符 str  --encode("utf-8")-->  字节 bytes
字节 bytes   --decode("utf-8")-->  文本字符 str

同一个字符在不同编码下可能对应不同字节,同一串字节用错误编码解码也可能报错或变成乱码。面试回答时一定要说清楚:Python 3 的 str 不是“某种编码的字符串”,它是 Unicode 文本;只有落到文件、网络、数据库驱动边界时,才需要明确编码成字节。

二、str 是文本,不是字节

Python 3 中,str 表示 Unicode 文本:

s = "Python你好"

它关注的是字符语义,而不是底层如何存成字节。一个字符到底占几个字节,取决于编码方式。

例如:

len("你")                  # 1 个字符
len("你".encode("utf-8"))  # 3 个字节
len("你".encode("gbk"))    # 2 个字节

这说明“字符长度”和“字节长度”是两回事。

表达式含义典型结果
len("A")字符数1
len("A".encode("utf-8"))UTF-8 字节数1
len("你")字符数1
len("你".encode("utf-8"))UTF-8 字节数3

三、bytes 是不可变字节序列

bytesb 前缀表示:

data = b"abc"
print(data[0])  # 97

注意,索引 bytes 得到的是整数,不是长度为 1 的 bytes。

bytes 常用于:

  • socket 网络收发;
  • HTTP body;
  • 图片、音频、压缩包等二进制文件;
  • 哈希、加密、签名;
  • 编码后的文本。

因为 bytes 不可变,不能原地改某个位置:

# data[0] = 65  # TypeError

bytes 的元素范围是 0 到 255,因为一个字节最多表示 256 种值。b"abc"a 的 ASCII 码是 97,所以 data[0] 得到 97;如果想得到长度为 1 的 bytes,要用切片 data[:1]。这点经常考,因为很多人以为索引 bytes 会得到 b"a"

data = b"abc"
print(data[0])   # 97
print(data[:1])  # b'a'

四、bytearray 是可变字节序列

如果需要修改字节内容,可以用 bytearray

data = bytearray(b"abc")
data[0] = 65
print(data)  # bytearray(b'Abc')

它适合处理需要原地修改的二进制缓冲区。不过普通业务文本处理很少需要它。比如网络协议解析、图片头部修改、二进制包拼装,bytearray 可以避免每改一次都创建新的 bytes。修改值也必须在 0 到 255 之间,否则不是合法字节。

buf = bytearray(b"abc")
buf[1] = 90
print(bytes(buf))  # b'aZc'

易错点:bytearray 可变的是字节内容,不是文本字符;往里面写入的是 0-255 的整数或字节片段,不会自动理解中文字符。

五、encodedecode 怎么记

从文本到字节:

text = "你好"
data = text.encode("utf-8")

从字节到文本:

text = data.decode("utf-8")

可以这样理解:

str --encode--> bytes
bytes --decode--> str

编码和解码必须使用匹配的字符集。用 UTF-8 编码的数据,如果用错误编码解码,可能报错,也可能变成乱码。

错误处理参数也值得知道,但不要滥用。errors="ignore" 会丢字节,errors="replace" 会替换成占位字符,适合日志兜底,不适合核心业务数据。面试里说“乱码”时要讲清楚本质:编码和解码规则不一致,或者原始字节本身不符合指定编码。

data = "你好".encode("utf-8")
# data.decode("ascii")  # UnicodeDecodeError
print(data.decode("utf-8"))  # 你好

六、文件和网络边界怎么选类型

文本模式:

with open("a.txt", "r", encoding="utf-8") as f:
    text = f.read()

读出来是 str

二进制模式:

with open("a.png", "rb") as f:
    data = f.read()

读出来是 bytes

处理文本文件时明确写 encoding="utf-8" 是好习惯,能减少不同系统默认编码导致的问题。

网络 socket、HTTP body、图片、压缩包、哈希输入这些场景通常处理 bytes;业务层展示、日志、JSON 字段通常处理 str。边界处要明确转换,不要让默认编码替你做决定。尤其是 Windows 和 Linux 默认编码可能不同,没写 encoding 的文本文件代码容易在换环境时出问题。

七、常见误区与追问

  • 误区:str 就是 UTF-8 字节串。 Python 3 的 str 是 Unicode 文本,UTF-8 是把它编码成 bytes 的一种规则。
  • 误区:len("你") 应该等于 3。 len(str) 数字符数,len(bytes) 数字节数,"你" 在 UTF-8 下才是 3 个字节。
  • 误区:bytes 索引会返回一个 bytes。 b"abc"[0] 返回整数 97,切片 b"abc"[:1] 才返回 b"a"
  • 追问:为什么 strbytes 不能直接拼接? 一个是文本层,一个是字节层,Python 要求你显式 encode 或 decode,避免隐式乱码。
  • 追问:什么时候用 bytearray 需要原地修改二进制缓冲区时用;普通业务文本处理通常不用。
  • 追问:文件打开为什么建议写 encoding="utf-8" 避免依赖系统默认编码,降低跨平台乱码风险。

八、加强记忆

把这题记成“文本走 str,传输和存储边界走 bytes,要原地改字节用 bytearray”。encode 是文本到字节,decode 是字节回文本;字符数和字节数不是一回事,编码不匹配才是乱码根源。面试回答时用 "你" 在 UTF-8 下 1 个字符、3 个字节这个例子,基本就能把核心讲清。