Skip to content

02-字符串进阶

本章代码基于 Python 3.11+ 编写

本章讲解字符串编码、二进制数据和实用技巧。


本章讲解字符串的底层存储机制:编码(字符→字节)、二进制数据类型(bytes/bytearray)及实用处理技巧。


概念铺垫

为什么需要了解字符串编码?一个真实的乱码场景

问题场景: 你从网络下载了一份中文文件,用 Python 读取后显示乱码,或者在不同系统间传输文字数据时出现错误。

不了解编码的困惑:

  • 为什么同样的中文字符在不同地方显示不一样?
  • bytesstr 有什么区别,为什么不能直接混用?
  • 如何正确读写包含中文的文件?

了解编码后的解决方案:

python
text = "你好,世界!"

# 编码:将字符串转为字节(用于传输/存储)
utf8_bytes = text.encode('utf-8')

# 解码:将字节还原为字符串(用于显示)
restored = utf8_bytes.decode('utf-8')
print(restored)  # 你好,世界!

这就是编码的价值:理解字符和字节的转换,避免乱码

编码的最简用法

python
# 编码:str → bytes
text = "Hello"
b = text.encode('utf-8')   # b'Hello'

# 解码:bytes → str
s = b.decode('utf-8')      # 'Hello'

L1 理解层:会用

字符串编码

字符串编码: 将人类可读的文本(str)转换为计算机存储的字节序列(bytes)的规则。

┌──────────────────────────────────────────────────┐
│  编码与解码流程                                    │
│                                                  │
│   str          encode(编码)      bytes           │
│  "你好"  ──────────────────→  b'\xe4\xbd\xa0...' │
│                                                  │
│   bytes        decode(解码)      str             │
│  b'\xe4...' ──────────────────→  "你好"          │
│                                                  │
│  常用编码:                                       │
│  UTF-8    → 支持所有语言,推荐使用               │
│  GBK/GB2312 → 中文系统常用(旧)                 │
│  ASCII    → 仅英文字符                           │
└──────────────────────────────────────────────────┘

最简示例:

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

关键代码解释:

代码含义说明
text.encode('utf-8')字符串编码为字节指定编码方式,不指定默认 utf-8
b.decode('utf-8')字节解码为字符串必须用相同编码解码,否则乱码

编码和解码:

python
text = "你好,世界!"

# 编码:字符串 -> 字节
utf8_bytes = text.encode('utf-8')
print(utf8_bytes)  # b'\xe4\xbd\xa0\xe5\xa5\xbd...'

# 解码:字节 -> 字符串
print(utf8_bytes.decode('utf-8'))  # 你好,世界!

Unicode 码点

Unicode 码点: 每个字符对应一个唯一的整数编号。

┌──────────────────────────────────────┐
│  ord() 与 chr() 互转                  │
│                                      │
│  ord('A')    → 65    (字符→码点)   │
│  chr(65)     → 'A'   (码点→字符)   │
│  ord('中')   → 20013                 │
│  chr(0x4E2D) → '中'  (十六进制码点)│
└──────────────────────────────────────┘
python
# 获取 Unicode 码点
char = '中'
print(ord(char))  # 20013

# 从码点获取字符
print(chr(20013))  # 中
print(chr(0x4E2D))  # 中

bytes 和 bytearray(二进制数据)

什么是二进制数据

在 Python 中,bytesbytearray 用于处理二进制数据(如文件、网络数据、图片等)。

┌─────────────────────────────────────────────────────┐
│         字符串 vs 二进制数据                          │
├─────────────────────────────────────────────────────┤
│                                                     │
│  str(字符串):                                    │
│  • 存储文本数据                                     │
│  • Unicode 编码                                    │
│  • 人类可读                                         │
│  • 例如:"Hello", "你好"                           │
│                                                     │
│  bytes(字节):                                    │
│  • 存储二进制数据                                   │
│  • 0-255 的整数序列                                │
│  • 计算机可读                                       │
│  • 例如:b'Hello', b'\x48\x65\x6c\x6c\x6f'        │
│                                                     │
└─────────────────────────────────────────────────────┘

bytes 类型

bytes 是不可变的二进制序列。

python
# 创建 bytes
b1 = b"Hello"           # 字节字面量
b2 = bytes([72, 101, 108, 108, 111])  # 从整数列表创建
b3 = "你好".encode('utf-8')           # 字符串编码

print(b1)   # b'Hello'
print(b2)   # b'Hello'
print(b3)   # b'\xe4\xbd\xa0\xe5\xa5\xbd'

# 访问元素(返回整数)
print(b1[0])    # 72('H' 的 ASCII 码)
print(b1[1:3])  # b'el'(切片返回 bytes)

# 不可变
# b1[0] = 74  # TypeError: 'bytes' object does not support item assignment

bytearray 类型

bytearray 是可变的二进制序列。

python
# 创建 bytearray
ba = bytearray(b"Hello")
print(ba)  # bytearray(b'Hello')

# 可修改
ba[0] = 74  # 'J'
print(ba)  # bytearray(b'Jello')

# 追加
ba.append(33)  # '!'
print(ba)  # bytearray(b'Jello!')

# 转换为 bytes
b = bytes(ba)
print(b)  # b'Jello!'

bytes vs bytearray

┌─────────────────────────────────────────────────────┐
│         bytes vs bytearray 对比                      │
├─────────────────────────────────────────────────────┤
│                                                     │
│  bytes                  bytearray                  │
│  ──────                 ──────────                 │
│  不可变                  可变                       │
│  创建后不能修改          可以修改元素               │
│  更安全                  更灵活                     │
│  可作为字典键            不能作为字典键             │
│                                                     │
│  使用场景:              使用场景:                 │
│  • 网络传输              • 需要修改二进制数据       │
│  • 文件读取              • 构建二进制协议           │
│  • 哈希计算              • 动态生成二进制           │
│                                                     │
└─────────────────────────────────────────────────────┘

编码和解码:

python
from __future__ import annotations

# 字符串 → bytes
text: str = "你好,Python!"
utf8_bytes: bytes = text.encode('utf-8')
gbk_bytes: bytes = text.encode('gbk')

print(f"UTF-8: {utf8_bytes}")
print(f"GBK: {gbk_bytes}")

# bytes → 字符串
decoded: str = utf8_bytes.decode('utf-8')
print(decoded)  # 你好,Python!

# 注意:编码和解码必须匹配
# utf8_bytes.decode('gbk')  # 乱码或错误!

常用操作:

python
# 十六进制转换
b = b'\x48\x65\x6c\x6c\x6f'
print(b.hex())  # '48656c6c6f'

# 从十六进制创建
b2 = bytes.fromhex('48656c6c6f')
print(b2)  # b'Hello'

# 长度
print(len(b'Hello'))  # 5
print(len('你好'.encode('utf-8')))  # 6(每个中文 3 字节)

# 拼接
b1 = b'Hello'
b2 = b' World'
print(b1 + b2)  # b'Hello World'

# 包含检查
print(b'ell' in b'Hello')  # True

实际场景

场景1:读取二进制文件

python
def read_binary_file(filepath: str) -> bytes:
    """读取二进制文件"""
    with open(filepath, 'rb') as f:  # 'rb' = read binary
        return f.read()

def write_binary_file(filepath: str, data: bytes) -> None:
    """写入二进制文件"""
    with open(filepath, 'wb') as f:  # 'wb' = write binary
        f.write(data)

场景2:处理网络数据

python
# 模拟接收网络数据
received: bytes = b'\x00\x05Hello'

# 解析协议头
length: int = int.from_bytes(received[:2], 'big')  # 5
data: bytes = received[2:2+length]  # b'Hello'

print(f"长度: {length}, 数据: {data}")

场景3:Base64 编码

python
import base64

# 编码
text: str = "Hello, Python!"
encoded: bytes = base64.b64encode(text.encode('utf-8'))
print(encoded)  # b'SGVsbG8sIFB5dGhvbiE='

# 解码
decoded: bytes = base64.b64decode(encoded)
print(decoded.decode('utf-8'))  # Hello, Python!

正则表达式

基本使用
python
import re

# 查找所有匹配
text = "My phone: 123-456-7890"
phones = re.findall(r'\d{3}-\d{3}-\d{4}', text)
print(phones)  # ['123-456-7890']

# 替换
text = "Hello   World"
result = re.sub(r'\s+', ' ', text)  # 多空格变单空格
print(result)  # Hello World

# 分割
text = "apple, banana; orange"
parts = re.split(r'[,\s;]+', text)
print(parts)  # ['apple', 'banana', 'orange']
常用模式
┌──────────┬──────────────────────────────┐
│   模式   │          说明                │
├──────────┼──────────────────────────────┤
│    \d    │ 数字                         │
│    \w    │ 字母、数字、下划线           │
│    \s    │ 空白字符                     │
│    .     │ 任意字符(除换行)           │
│    *     │ 0 次或多次                   │
│    +     │ 1 次或多次                   │
│    ?     │ 0 次或 1 次                   │
│    []    │ 字符集合                     │
│    ()    │ 分组                         │
└──────────┴──────────────────────────────┘
实用示例
python
import re

# 提取邮箱
def extract_emails(text):
    pattern = r'\b[\w.]+@[\w.]+\.\w+\b'
    return re.findall(pattern, text)

# 验证手机号
def is_valid_phone(phone):
    pattern = r'^1[3-9]\d{9}$'
    return bool(re.match(pattern, phone))

# 提取 URL
def extract_urls(text):
    pattern = r'https?://[\w./-]+'
    return re.findall(pattern, text)

实用技巧

文本清理
python
def clean_text(text):
    """清理文本:去除空白、标准化空格"""
    text = text.strip()
    text = " ".join(text.split())
    return text

print(clean_text("  Hello    World   "))  # Hello World
命名转换
python
import re

def snake_to_camel(name):
    """snake_case 转 camelCase"""
    parts = name.split("_")
    return parts[0] + "".join(word.capitalize() for word in parts[1:])

def camel_to_snake(name):
    """camelCase 转 snake_case"""
    return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()

print(snake_to_camel("hello_world"))   # helloWorld
print(camel_to_snake("helloWorld"))    # hello_world
截断文本
python
def truncate(text, length=50, suffix="..."):
    """截断文本到指定长度"""
    if len(text) <= length:
        return text
    return text[:length - len(suffix)] + suffix

print(truncate("这是一个很长的文本", 10))  # 这是一个很...

L2 实践层:用好

推荐做法

做法原因示例
正则对象预编译避免每次调用重复解析模式EMAIL_RE = re.compile(r"...")
用 raw string 写正则不需要双重转义反斜杠r"\d{3}-\d{4}"
读写文件明确指定编码避免跨平台编码不一致open("f.txt", encoding="utf-8")
bytes 处理二进制数据类型安全,防止 str/bytes 混用data: bytes = f.read()
需要修改时用 bytearray避免频繁创建新 bytes 对象ba = bytearray(data)
re.match 配合原始字符串从起始判断可读性更好re.match(r"^1[3-9]\d{9}$", phone)
用户可见数据编码错误用 replace保留出问题痕迹data.decode("utf-8", errors="replace")
内部数据编码错误用 strict快速暴露编码异常data.decode("utf-8", errors="strict")

反模式:不要这样做

正则表达式重复编译
python
# ❌ 错误做法:每次调用都重新编译正则
def extract_emails(text: str) -> list[str]:
    return re.findall(r'\b[\w.]+@[\w.]+\.\w+\b', text)

def is_valid_email(email: str) -> bool:
    return bool(re.match(r'^[\w.]+@[\w.]+\.[a-z]{2,}$', email))

# 问题:
# 1. 每次调用都重新解析和编译正则模式
# 2. 在高频调用的场景(循环、请求处理)性能浪费明显
# 3. 正则模式散落各处,难以统一管理
python
# ✅ 正确做法:预编译正则对象
import re

EMAIL_PATTERN = re.compile(r'\b[\w.]+@[\w.]+\.\w+\b')
EMAIL_VALID = re.compile(r'^[\w.]+@[\w.]+\.[a-z]{2,}$')

def extract_emails(text: str) -> list[str]:
    return EMAIL_PATTERN.findall(text)

def is_valid_email(email: str) -> bool:
    return bool(EMAIL_VALID.match(email))
路径中的反斜杠陷阱
python
# ❌ 错误做法:普通字符串中的反斜杠被转义
path = "C:\Users\new_files\data.txt"
# 实际值: C:\Users
#                   ew_files\data.txt
# \n 被解释为换行符,\f 被解释为换页符!

# ❌ 错误做法:手动转义反斜杠
path = "C:\\Users\\new_files\\data.txt"
# 勉强可用,但冗长易遗漏
python
# ✅ 正确做法:用 raw string
path = r"C:\Users\new_files\data.txt"  # 反斜杠字面保留

# ✅ 更好的做法:用 pathlib(跨平台)
from pathlib import Path
path = Path("C:/Users/new_files/data.txt")  # Windows 也接受正斜杠
编码错误处理不当
python
# ❌ 错误做法:不指定编码,依赖系统默认
with open("data.txt") as f:
    content = f.read()  # Windows 上可能用 GBK,Linux 上用 UTF-8
# 问题:同一份代码在不同系统上行为不一致,导致乱码

# ❌ 错误做法:忽略编码错误
text = data.decode("utf-8", errors="ignore")  # 悄悄丢弃无法解码的字节!
# 问题:丢失数据且没有错误提示,静默失败
python
# ✅ 正确做法:显式指定编码
with open("data.txt", encoding="utf-8") as f:
    content = f.read()

# ✅ 正确做法:用 errors="replace" 保留线索
text = data.decode("utf-8", errors="replace")  # 非法字节用 � 替换
# 至少能看到哪里有编码问题

# ✅ 正确做法:严格模式用于内部数据
text = data.decode("utf-8", errors="strict")   # 编码错误立即抛异常
# 内部系统数据不应有编码问题,严格模式快速暴露 bug
str 和 bytes 混用
python
# ❌ 错误做法:str 和 bytes 混合操作
text = "hello"
data = b"world"
# result = text + data  # TypeError!

# ❌ 错误做法:用 str 读写二进制文件
with open("image.png", "r") as f:  # 二进制文件不该用文本模式
    data = f.read()  # 可能因编码错误而失败
python
# ✅ 正确做法:明确区分文本和二进制
text = "hello"
data = b"world"
text += data.decode("utf-8")  # 先解码再拼接

# ✅ 正确做法:二进制文件用二进制模式
with open("image.png", "rb") as f:
    data: bytes = f.read()

适用场景

场景是否推荐原因
高频调用的正则(循环、请求处理)✅ 预编译编译一次,复用多次,性能提升 3-10x
一次性匹配❌ 不需要手动预编译re 模块内部自动缓存最近 ~512 个模式
Windows 文件路径✅ raw string反斜杠不被转义,路径字面清晰
跨平台路径✅ pathlib消除 OS 差异
与外部系统交互的数据✅ 明确指定编码避免隐式依赖系统默认编码
纯内部系统数据✅ UTF-8 + strict快速发现编码异常,不容忍错误
网络数据解析✅ bytes + struct类型安全,协议解析清晰
需要频繁修改的二进制数据✅ bytearray支持原地修改,避免重复创建
只读二进制数据(文件读取、哈希计算)✅ bytes不可变性保证数据不被意外修改

字符串构建性能(回顾)

python
# ❌ 不推荐:循环中使用 +
result = ""
for i in range(1000):
    result += str(i)  # 每次创建新字符串

# ✅ 推荐:使用 join
result = "".join(str(i) for i in range(1000))

# ✅ 推荐:列表收集后 join
parts = []
for i in range(1000):
    parts.append(str(i))
result = "".join(parts)
方式时间复杂度内存推荐场景
+ 拼接少量字符串O(n)临时对象少≤ 5 个字符串
join() 拼接大量O(n) 总长度一次分配≥ 10 个元素
io.StringIOO(n)动态缓冲区需要多次追加、回退的复杂构建

L3 专家层:深入

Python 如何实现编码

UTF-8 变长编码原理

UTF-8 是 Unicode 的变长编码方案,根据码点范围使用 1-4 字节:

UTF-8 编码规则:
┌─────────────────────────────────────────────────────────────┐
│  Unicode 码点范围           UTF-8 字节序列     字节数        │
│  ─────────────────────────────────────────────────────      │
│  U+0000 ~ U+007F           0xxxxxxx              1 字节     │
│  (ASCII 字符 — 英文、数字、基本符号)                       │
│                                                             │
│  U+0080 ~ U+07FF           110xxxxx 10xxxxxx      2 字节    │
│  (拉丁扩展、阿拉伯文、希腊文)                               │
│                                                             │
│  U+0800 ~ U+FFFF           1110xxxx 10xxxxxx      3 字节    │
│  (BMP 字符 — 中文、日文、韩文)                10xxxxxx     │
│                                                             │
│  U+10000 ~ U+10FFFF        11110xxx 10xxxxxx      4 字节    │
│  (非 BMP — emoji、罕见汉字)  10xxxxxx 10xxxxxx            │
│                                                             │
│  实测示例:                                                  │
│  'A'   (U+0041)  → \x41           → 1 字节                  │
│  'é'   (U+00E9)  → \xC3\xA9       → 2 字节                  │
│  '中'  (U+4E2D)  → \xE4\xB8\xAD   → 3 字节                  │
│  '😂'  (U+1F602) → \xF0\x9F\x98\x82 → 4 字节                │
│                                                             │
│  设计特点:                                                  │
│  • 向后兼容 ASCII:纯 ASCII 文本的 UTF-8 就是 ASCII 本身     │
│  • 无字节序问题:UTF-8 是字节流,不存在大端/小端             │
│  • 自同步:任意字节的位置都可判断是否是字符起始字节          │
└─────────────────────────────────────────────────────────────┘

验证代码:

python
import sys

# 不同语言字符的 UTF-8 字节数
chars = [
    ("英文字符 'A'", "A"),
    ("中文 '中'", "中"),
    ("emoji '😂'", "😂"),
]

for label, ch in chars:
    encoded = ch.encode("utf-8")
    print(f"{label}:")
    print(f"  码点: U+{ord(ch):04X}")
    print(f"  UTF-8 字节: {encoded.hex(' ')}")
    print(f"  字节数: {len(encoded)}")
    print()

# 字节数差异:同一个 "字符" 在内存中的表现不同
text = "A中😂"
print(f"字符数: {len(text)}")                     # 3(3 个码点)
print(f"UTF-8 字节数: {len(text.encode('utf-8'))}")  # 8(1+3+4 字节)

# Python 内部存储 vs UTF-8 编码
print(f"\nstr 对象内存: {sys.getsizeof(text)} 字节")
print(f"UTF-8 编码后: {len(text.encode('utf-8'))} 字节")
Python str 内部编码验证
python
import sys

# Python 根据字符串内容自动选择最紧凑的内部编码
ascii_only = "hello"        # 全 ASCII → 1 字节/字符
bmp_only = "你好世界"        # 全 BMP → 2 字节/字符
has_emoji = "Hello 😂"       # 含非 BMP → 4 字节/字符

print(f"纯 ASCII(5 字符): {sys.getsizeof(ascii_only)} 字节")
print(f"纯 BMP(4 字符):   {sys.getsizeof(bmp_only)} 字节")
print(f"含 Emoji(7 字符):  {sys.getsizeof(has_emoji)} 字节")

# 紧凑存储节省内存 — 大规模文本对比
big_ascii = "a" * 10000
big_chinese = "中" * 10000
print(f"\n10K ASCII:  {sys.getsizeof(big_ascii)} 字节(~{sys.getsizeof(big_ascii)/1024:.0f} KB)")
print(f"10K 中文:     {sys.getsizeof(big_chinese)} 字节(~{sys.getsizeof(big_chinese)/1024:.0f} KB)")
# 中文字符的内存占用约是 ASCII 的 2 倍(内部 UCS-2 vs Latin-1)

正则表达式回溯性能

回溯原理

正则引擎在匹配失败时会回溯到上一个决策点尝试其他路径。这一机制在正常模式下是灵活的,但嵌套量词可能导致灾难性性能:

回溯示意 — 模式 r"(a|ab)+c" 匹配 "abc":
┌─────────────────────────────────────────────────────────────┐
│  步骤 1: (a|ab) 匹配 "a" ✓ → 剩余 "bc" 待匹配               │
│  步骤 2: (a|ab) 无法匹配 "b" 开头的 "bc" → 回溯,尝试 ab    │
│  步骤 3: ab 匹配 "ab" ✓ → 剩余 "c" 待匹配                   │
│  步骤 4: c 匹配 "c" ✓ → 匹配成功                            │
│                                                             │
│  危险模式:r"(x+)+y" 匹配 "xxxxxxxx"(不含 y)               │
│  → 每增加一个 x,回溯步骤呈指数增长!这称为 ReDoS 攻击       │
│  → 20 个 x:毫秒级;30 个 x:可能数秒;40 个 x:数分钟       │
└─────────────────────────────────────────────────────────────┘

验证代码:

python
import re
import timeit

# 编译两种方式:内联 vs 预编译
COMPILED = re.compile(r"\d{3}-\d{3}-\d{4}")

def search_inline():
    pattern = r"\d{3}-\d{3}-\d{4}"
    return re.search(pattern, "Phone: 123-456-7890")

def search_compiled():
    return COMPILED.search("Phone: 123-456-7890")

# 性能对比
print("正则编译 vs 内联性能(100K 次):")
print(f"  内联每次编译: {timeit.timeit(search_inline, number=100000):.4f}s")
print(f"  预编译:       {timeit.timeit(search_compiled, number=100000):.4f}s")

# 危险回溯示例(仅作学习,执行可能很慢)
# ⚠️ 下面的代码可能极慢,仅供理解回溯机制
# re.match(r"(x+)+y$", "x" * 30)  # 嵌套量词导致指数级回溯!
编码/解码性能验证
python
import timeit

text = "你好,世界!Python 编程" * 1000

# encode 性能
t_encode = timeit.timeit(
    "text.encode('utf-8')",
    globals={"text": text},
    number=10000
)
print(f"UTF-8 编码(54KB × 10,000 次): {t_encode:.4f}s")

# decode 性能
encoded = text.encode("utf-8")
t_decode = timeit.timeit(
    "encoded.decode('utf-8')",
    globals={"encoded": encoded},
    number=10000
)
print(f"UTF-8 解码(78KB × 10,000 次): {t_decode:.4f}s")

性能考量

操作时间复杂度说明
s.encode('utf-8')O(n)遍历每个码点,计算 UTF-8 字节序列
b.decode('utf-8')O(n)解析字节流,重建 Unicode 码点
ASCII 编码/解码O(n)逐字节复制,无码点转换,略快于 UTF-8
re.compile()O(m),m = 模式长度编译成内部状态机,一次成本
re.search()(预编译)O(n) 平均使用编译后的自动机顺序扫描
re.search()(内联)O(m + n)每次多花 m 时间编译模式
危险回溯正则O(2^n) 最坏嵌套量词匹配失败时指数级回溯
bytes.hex()O(n)每个字节转 2 个十六进制字符
int.from_bytes()O(1)固定字节数,直接位运算
base64.b64encode()O(n)每 3 字节编为 4 字符

设计动机

设计选择原因实际影响
str 与 bytes 严格分离(Python 3)消除 Python 2 隐式编解码导致的乱码必须显式 encode/decode,边界清晰
str 内部紧凑存储ASCII 文本占 1 字节/字符,比 Python 2 节省约 50% 内存英文为主的应用内存显著降低
re 模块自动缓存最近 ~512 个模式减少用户手动 compile 的心智负担多数一次性场景无需手动 compile
UTF-8 作为默认编码全球通用,向后兼容 ASCII处理中文无需额外配置
开放 errors 参数(strict/replace/ignore)用户可根据场景选择容错策略避免一刀切的崩溃或静默丢失数据
正则引擎基于回溯而非 DFA支持反向引用、捕获组等高级特性功能强大,但不当使用导致 ReDoS 风险

知识关联

字符串进阶知识关联:

                         ┌─────────────────┐
                         │   Unicode 标准   │
                         │   (ISO 10646)   │
                         └─────────────────┘

                     ┌─────────┼─────────┐
                     ↓         ↓         ↓
               ┌─────────┐ ┌─────────┐ ┌─────────┐
               │ UTF-8   │ │ UTF-16  │ │ UTF-32  │
               │ (变长)  │ │ (变长)  │ │ (定长)  │
               └─────────┘ └─────────┘ └─────────┘


               ┌─────────────┐     ┌─────────────────┐
               │  str 类型    │←───→│  bytes 类型      │
               │  (内部存储)  │     │  (外部表示)      │
               └─────────────┘     └─────────────────┘
                     │                      │
                     ↓                      ↓
               ┌─────────────┐     ┌─────────────────┐
               │  ord/chr    │     │  文件/网络 I/O   │
               │  (码点操作) │     │  (字节流处理)    │
               └─────────────┘     └─────────────────┘


                                    ┌─────────────────┐
                                    │  bytearray       │
                                    │  (可变二进制)    │
                                    └─────────────────┘

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  正则表达式     │────→│  NFA/DFA 自动机 │────→│  回溯机制       │
│  (re 模块)     │←────│  (匹配引擎)     │←────│  (性能关键)     │
└─────────────────┘     └─────────────────┘     └─────────────────┘


┌─────────────────┐     ┌─────────────────┐
│  re.compile()   │     │  灾难性回溯     │
│  (预编译缓存)   │     │  (ReDoS 攻击)   │
└─────────────────┘     └─────────────────┘
前置依赖:字符串基础(str 类型、索引、切片、方法)

当前概念:字符串进阶(编码、bytes/bytearray、正则表达式)

后续依赖:
├── 文件 I/O(文本/二进制读写,编码指定)
├── 网络编程(HTTP 请求/响应中的字节处理)
├── 数据科学(CSV/JSON 文本解析、数据清洗)
├── Web 开发(请求/响应编码、模板引擎)
└── 系统编程(协议解析、二进制格式处理)

本章小结

┌─────────────────────────────────────────────────────────────┐
│                    字符串进阶 知识要点                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   编码:                                                     │
│   ✓ encode() / decode()                                    │
│   ✓ ord() / chr()                                          │
│                                                             │
│   二进制数据:                                               │
│   ✓ bytes:不可变二进制序列                                 │
│   ✓ bytearray:可变二进制序列                               │
│   ✓ hex() / fromhex():十六进制转换                         │
│   ✓ 文件读写:'rb' / 'wb' 模式                              │
│                                                             │
│   正则表达式:                                               │
│   ✓ re.findall() / re.sub() / re.match()                   │
│   ✓ 常用模式:\d \w \s . * + ?                              │
│                                                             │
│   性能优化:                                                 │
│   ✓ 使用 join 而非 + 连接大量字符串                         │
│   ✓ 高频正则预编译为 re.compile 对象                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘