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

结合场景再看三个关注点

  1. 中文 UTF-8 多字节:字符数 ≠ 字节数。
  2. 编解码编码必须一致,否则乱码或异常。
  3. 文本模式 open(..., encoding="utf-8") 可自动编解码。

核心概念与准确模型

类型含义可变
strUnicode 码点序列
bytes0–255 字节
bytearray可变字节
  • f-string、format、拼接 +/join
  • 常用方法:split/strip/replace/startswith
  • 原始字符串 r"..." 减少反斜杠转义

边界情况与反直觉行为

  1. strbytes 不能隐式拼接
  2. 默认编码因平台而异——文件 I/O 应显式 encoding=
  3. 规范化:同一视觉字符可能有多码点序列(NFC/NFD)。

常见误区

[!warning] 常见误区:把 Python 2 的“str 即字节”直觉搬到 3 错误理解:字符串就是字节数组。
正确模型:文本与字节分离;边界显式转换。

工程实践

  • 项目统一 UTF-8。
  • 日志与 API JSON 用文本;签名/哈希用字节。
  • 大文本拼接用 join 或 io 缓冲。

本节总结

先分清文本层与字节层,再处理切片、长度与 I/O。乱码问题几乎总是边界编码问题。

自测题

  1. 为什么示例里 chars 与 utf8 bytes 不同?
  2. b"hi" + "hi" 会怎样?
参考答案
  1. 中文在 UTF-8 中多字节编码。
  2. TypeError,bytes 与 str 不能直接加。

延伸阅读与资料来源

资料类型支撑内容
Text Sequence Type文档str
Binary Sequence Types文档bytes
Unicode HOWTOHOWTO编码实践
创建于 2026/7/15 更新于 2026/7/15