Python 字符串与字节
str 是不可变 Unicode 文本,bytes 是不可变字节序列;在文件/网络边界显式编码解码。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
Python 字符串与字节
这个概念为什么出现
用户看见的是文本,磁盘和网卡上是字节。Python 3 强制分开:
str:Unicode 文本bytes/bytearray:字节
混用会在读写文件、HTTP、加密时出现 TypeError 或乱码。
[!abstract] 一句话理解
str不可变文本;bytes不可变字节串;越过 I/O 边界时用明确编码encode/decode(常见 UTF-8)。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:客服备注写入 UTF-8 文件并回读
工单备注含中文。写入磁盘必须是字节;读回要按同一编码解码。
# ticket_note_codec.py
# 业务意图:把中文备注安全写入字节并解码回来。
# 教学点:
# - str.encode / bytes.decode;
# - len(str) 是字符数,len(bytes) 是字节数;
# - 错误处理 errors= 可选。
from pathlib import Path
def save_note(path: Path, note: str) -> None:
data = note.encode("utf-8") # 文本 -> 字节
path.write_bytes(data)
def load_note(path: Path) -> str:
return path.read_bytes().decode("utf-8")
def main() -> None:
p = Path("/tmp/ticket_note_demo.txt")
text = "用户说:无法登录"
save_note(p, text)
back = load_note(p)
print("roundtrip:", back)
print("chars:", len(text), "utf8 bytes:", len(text.encode("utf-8")))
if __name__ == "__main__":
main()
建议运行:
python ticket_note_codec.py
期望输出:
roundtrip: 用户说:无法登录
chars: 8 utf8 bytes: 24
结合场景再看三个关注点
- 中文 UTF-8 多字节:字符数 ≠ 字节数。
- 编解码编码必须一致,否则乱码或异常。
- 文本模式
open(..., encoding="utf-8")可自动编解码。
核心概念与准确模型
| 类型 | 含义 | 可变 |
|---|---|---|
str | Unicode 码点序列 | 否 |
bytes | 0–255 字节 | 否 |
bytearray | 可变字节 | 是 |
- f-string、
format、拼接+/join - 常用方法:
split/strip/replace/startswith - 原始字符串
r"..."减少反斜杠转义
边界情况与反直觉行为
str与bytes不能隐式拼接。- 默认编码因平台而异——文件 I/O 应显式
encoding=。 - 规范化:同一视觉字符可能有多码点序列(NFC/NFD)。
常见误区
[!warning] 常见误区:把 Python 2 的“str 即字节”直觉搬到 3 错误理解:字符串就是字节数组。
正确模型:文本与字节分离;边界显式转换。
工程实践
- 项目统一 UTF-8。
- 日志与 API JSON 用文本;签名/哈希用字节。
- 大文本拼接用
join或 io 缓冲。
本节总结
先分清文本层与字节层,再处理切片、长度与 I/O。乱码问题几乎总是边界编码问题。
自测题
- 为什么示例里 chars 与 utf8 bytes 不同?
b"hi" + "hi"会怎样?
参考答案
- 中文在 UTF-8 中多字节编码。
TypeError,bytes 与 str 不能直接加。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Text Sequence Type | 文档 | str |
| Binary Sequence Types | 文档 | bytes |
| Unicode HOWTO | HOWTO | 编码实践 |