2.3 字符串
目标
- 读懂字符串字面量的各种写法:单/双/三引号、转义、原始字符串。
- 熟练使用索引、切片和高频方法(
split、join、strip、replace、startswith……)。 - 理解字符串不可变;区分
str(文本)与bytes(字节)。
核心概念
字面量
Python · 可运行
python
a = '单引号'
b = "双引号,内部可直接用 ' 号"
c = """三引号可以跨行,
常用于文档字符串和多行文本"""
d = "换行\n制表\t反斜杠\\"
e = r"C:\new\table" # 原始字符串:反斜杠不转义,常用于正则和 Windows 路径
f = "相邻的" "字面量" "会自动拼接"
print(a, b, c, d, e, f, sep="\n")索引与切片
字符串是序列:可以用 s[i] 取单个字符,s[start:stop:step] 取子串(含 start、不含 stop)。负数索引从末尾数起。
Python · 可运行
python
s = "minimal_agent.py"
print(s[0], s[-1]) # m y
print(s[:7]) # minimal
print(s[-3:]) # .py
print(s[::-1]) # 反转
print(len(s), "agent" in s)切片越界不会报错,索引越界会抛 IndexError。切片的完整规则在 4.1 详细讲。
高频方法
字符串方法都返回新字符串,原字符串不变。
| 方法 | 作用 | 例子 → 结果 |
|---|---|---|
s.split(sep=None) | 拆分为列表;不传参数时按任意空白拆分并丢弃空串 | "a b\n c".split() → ['a', 'b', 'c'] |
sep.join(iterable) | 用 sep 连接字符串序列 | "-".join(["a", "b"]) → 'a-b' |
s.strip() / lstrip / rstrip | 去两端空白(或指定字符) | " hi \n".strip() → 'hi' |
s.replace(old, new) | 替换全部出现 | "a.b.c".replace(".", "/") → 'a/b/c' |
s.startswith(p) / endswith | 前后缀判断,可传元组 | "x.py".endswith((".py", ".pyi")) → True |
s.removeprefix(p) / removesuffix | 去掉前缀/后缀(3.9 起) | "v1.2".removeprefix("v") → '1.2' |
s.find(sub) / s.index(sub) | 查找位置;找不到时 find 返回 -1,index 抛 ValueError | "abc".find("z") → -1 |
s.upper() / lower() / title() | 大小写 | "Agent".lower() → 'agent' |
s.count(sub) | 出现次数 | "banana".count("a") → 3 |
s.splitlines() | 按行拆分 | "a\nb".splitlines() → ['a', 'b'] |
s.isdigit() 等 | 字符类别判断 | "42".isdigit() → True |
Python · 可运行
python
line = " role=user ; content=你好 "
pairs = [p.strip() for p in line.strip().split(";")]
print(pairs)
key, value = pairs[0].split("=", 1) # 第二个参数:最多拆分 1 次
print(key, value)
print("、".join(["北京", "上海", "深圳"]))
print("=" * 20) # 重复不可变性
字符串创建后不能修改,所有“修改”都是创建新字符串。
Python · 可运行演示报错
python
s = "hello"
s[0] = "H"正确做法:s = "H" + s[1:] 或 s = s.capitalize()。
str 与 bytes
str 是 Unicode 文本;bytes 是原始字节。网络、文件、加密等场景会遇到 bytes,二者通过编码转换:
Python · 可运行
python
text = "你好"
data = text.encode("utf-8") # str → bytes
print(data, len(text), len(data)) # 2 个字符,6 个字节
print(data.decode("utf-8")) # bytes → str
print(type(b"raw bytes"))易错点
- 把
join写反:是"分隔符".join(列表),不是列表.join(...);且列表元素必须都是str,否则TypeError。 split()与split(" ")不同:前者按任意空白拆分并丢弃空串,后者严格按单个空格拆分。- 在循环里用
+=拼接大量字符串:每次都创建新对象;收集到列表最后"".join(...)更清晰高效。 strip("abc")不是去掉子串 "abc":它去掉两端属于字符集合{a, b, c}的任意字符;去前后缀用removeprefix/removesuffix。
Python · 可运行
python
print(" a b ".split(), " a b ".split(" "))
print("abcxcba".strip("abc")) # 'x',不是 'xcba'
print("prefix_name".removeprefix("prefix_"))Python · 可运行演示报错
python
print(", ".join(["第", 1, "轮"])) # 元素必须都是字符串对照
| 操作 | Python | JS | Java |
|---|---|---|---|
| 长度 | len(s) | s.length | s.length() |
| 子串 | s[1:4] | s.slice(1, 4) | s.substring(1, 4) |
| 包含 | "a" in s | s.includes("a") | s.contains("a") |
| 连接列表 | ",".join(xs) | xs.join(",") | String.join(",", xs) |
| 去空白 | s.strip() | s.trim() | s.strip() |
| 多行文本 | """...""" | 模板字符串 `...` | 文本块 """...""" |
| 字符类型 | 无单独 char,取一个字符得到长度为 1 的 str | 同左 | char |
读代码
python
final_text = "".join([b.text for b in resp.content if b.type == "text"])模型回复可能包含多个文本块;先用列表推导式取出每块的 text(得到字符串列表),再用空字符串 "" 把它们首尾相接。若写 "\n".join(...) 则每块之间会换行。
真实代码里另一种常见写法是解析简单的 KEY=VALUE 行,这正是 .env 文件的格式:
python
for line in text.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
key, _, value = line.partition("=")partition 返回三元组 (前, 分隔符, 后),找不到分隔符时后两项为空串,不会抛错。
练习
练习 1:解析 .env 文本
实现 parse_env(text):返回字典。规则:忽略空行和以 # 开头的行;每行按第一个 = 拆成键和值,键和值都去掉两端空白。
练习
def parse_env(text):
result = {}
# 在这里写代码
return result
快捷键:⌘/Ctrl + Enter 提交检查
练习 2:拼接文本块
blocks 是若干 (类型, 文本) 元组。实现 join_text(blocks):只取类型为 "text" 的文本,用 "" 连接返回。
练习
def join_text(blocks):
...
快捷键:⌘/Ctrl + Enter 提交检查
小结
- 字符串是不可变序列:支持索引、切片、
in、len。 - 方法返回新字符串;
"sep".join(列表)连接,split()拆分。 str是文本,bytes是字节,用encode/decode转换。