Python 字符串:split、replace、strip、join、切片与 f-字符串
Python 字符串(类型 str)是不可变的 Unicode 字符序列。split() 将字符串切分成列表,join() 把列表重新拼接,replace() 替换子串,strip() 去除两端空白;每个方法都返回新的字符串。插入值最方便的方式是 f-字符串:f"{name}: {price:.2f}"。
字符串几乎出现在每个程序中:用户输入、文件名、CSV 行、API 响应。str 类型以 Unicode 存储文本,因此中文、俄语和表情符号无需任何设置即可使用。最常用的方法是 split、replace、strip 和 join,输出值则最适合用 f-字符串。下面用示例逐一讲解。
Python 字符串的结构
字符串可以用单引号或双引号括起来,两者没有区别:'咖啡' 和 "咖啡" 完全相同。三引号可以创建多行字符串,其中的换行会原样保留。
name = "咖啡"
note = """第一行
第二行"""
print(len(name)) # 2 — 字符串的长度(字符数)
字符串最重要的特性是不可变性。方法不会修改原字符串,而是返回一个新字符串。因此 s.replace("a", "b") 如果不赋值就什么也不会改变——必须写成 s = s.replace("a", "b")。这是新手最常犯的错误。
转义字符、换行与原始字符串
换行用 \n 表示,制表符用 \t,反斜杠用 \\。前缀 r 会创建“原始”字符串:其中的反斜杠不再被处理。这对 Windows 路径和正则表达式很方便。
print("合计:\n350 ₽")
path = r"C:\new\table.csv" # \n 和 \t 不会被当作转义字符
较长的表达式可以用括号括起来并换行:括号内相邻的字符串字面量会被 Python 自动拼接。
split:把字符串拆分成列表
split() 按分隔符切分字符串,并返回列表。不带参数时,它按任意空白字符切分,并忽略重复的空格——这对解析命令很方便。
"add 咖啡 250".split() # ['add', '咖啡', '250']
"2026-10-16".split("-") # ['2026', '10', '16']
"a,b,,c".split(",") # ['a', 'b', '', 'c']
"key=value=x".split("=", 1) # ['key', 'value=x']
注意区别:指定分隔符时,空片段会被保留。第二个参数 maxsplit 限制切分次数,rsplit() 则从右侧切分。若要把文本拆成行,使用 splitlines():它同时识别 \n 和 \r\n,并且不会在末尾留下空元素。
text = "咖啡\n打车\n"
text.split("\n") # ['咖啡', '打车', '']
text.splitlines() # ['咖啡', '打车']
join:把列表拼接成字符串
join() 是相反的操作。它由分隔符字符串调用,参数是字符串列表:
items = ["咖啡", "打车", "午饭"]
print(", ".join(items)) # 咖啡, 打车, 午饭
print("\n".join(items)) # 每个条目占一行
所有元素都必须是字符串,否则会得到 TypeError: sequence item 0: expected str instance, int found。数字要先转换:", ".join(str(x) for x in amounts)。
字符串拼接与合并
两个字符串可以用 + 相加,用 * 重复:"-" * 20。但在循环中用 += 拼接成百上千个片段很慢,因为每次都会创建新字符串。应该把各部分收集到列表中,然后用一次 join() 合并。字符串不能直接与数字相加:"合计:" + 5 会引发 TypeError,需要使用 str() 或 f-字符串。
replace:替换子串
replace(old, new) 替换所有出现的子串。第三个参数限制替换的次数。
price = "1 250,50"
price = price.replace(" ", "").replace(",", ".")
print(float(price)) # 1250.5
"a-b-c".replace("-", "+", 1) # 'a+b-c'
该方法区分大小写,并且只匹配完全相同的文本。若要按模式替换(例如“所有数字”),需要使用 re 模块和 re.sub() 函数。
strip、lstrip、rstrip:去除首尾字符
strip() 从两端去除空格、制表符和换行符。lstrip() 只处理左侧,rstrip() 只处理右侧。对用户输入或文件中的字符串,这通常是第一步要做的事。
raw = " 咖啡 \n"
raw.strip() # '咖啡'
raw.rstrip() # ' 咖啡'
"xx咖啡xx".strip("x") # '咖啡'
参数是一组字符,而不是子串:"abc文本cba".strip("abc") 会从两端去掉所有的 a、b、c,顺序不限。若要精确去掉前缀或后缀,请使用 removeprefix() 和 removesuffix()(自 Python 3.9 起可用)。
其他常用字符串方法
| 方法 | 作用 | 示例 → 结果 |
|---|---|---|
lower()、upper() | 大小写转换 | "Coffee".lower() → 'coffee' |
startswith()、endswith() | 检查开头与结尾 | "a.csv".endswith(".csv") → True |
find() | 子串的位置,未找到返回 -1 | "咖啡".find("啡") → 1 |
count() | 出现次数 | "banana".count("a") → 3 |
isdigit() | 是否只包含数字? | "250".isdigit() → True |
zfill() | 用前导零补足长度 | "7".zfill(3) → '007' |
检查字符串是否包含某个子串,最简单的方法是运算符 in:if "咖啡" in text.lower():。字符串用 == 逐字符比较,且区分大小写;若要忽略大小写比较,请把两者都转换为 casefold() 的结果。
字符串切片
字符串是序列,因此可以通过从 0 开始的索引访问字符,负索引从末尾开始计数。切片 s[start:stop:step] 返回子串;右边界不包含在内。
s = "Python"
s[0] # 'P'
s[-1] # 'n'
s[0:3] # 'Pyt'
s[2:] # 'thon'
s[::2] # 'Pto'
s[::-1] # 'nohtyP' — 反转字符串
切片超出边界时不会报错:s[0:100] 返回整个字符串。但 s[100] 会抛出 IndexError。按索引修改字符是不行的(s[0] = "J" 会得到 TypeError),需要创建新字符串:"J" + s[1:]。
Python 中的 f-字符串
字符串前面加上字母 f,花括号中的表达式就会被计算并插入文本中。自 Python 3.6 起,这是格式化字符串的主要方式:比 format() 简短,也比旧的 % 运算符更快。
item = "咖啡"
price = 250
print(f"{item}: {price} ₽") # 咖啡: 250 ₽
print(f"打折后:{price * 0.9} ₽") # 打折后:225.0 ₽
print(f"{item=}") # item='咖啡' — 调试时很方便
数字格式化与对齐
在花括号内的冒号之后写格式说明符,它决定舍入、千位分隔符、宽度和对齐方式:
| 写法 | 结果 | 含义 |
|---|---|---|
f"{3.14159:.2f}" | 3.14 | 保留两位小数 |
f"{1250000:,}" | 1,250,000 | 千位分隔符 |
f"{1250000:_}" | 1_250_000 | 用下划线代替逗号 |
f"{0.256:.1%}" | 25.6% | 百分比 |
f"{'咖啡':<10}|" | 咖啡 | | 左对齐,宽度 10 |
f"{250:>8}" | 250 | 右对齐 |
f"{7:03d}" | 007 | 用零补足 |
对齐功能适合在终端中输出表格:f"{name:<12}{amount:>10.2f}" 可以让各列整齐排列。注意,格式化只用于输出。金额应以分为单位保存(int)或使用 Decimal,而不是 float:0.1 + 0.2 的结果是 0.30000000000000004。
f-字符串中的引号与换行
从 Python 3.12 起(PEP 701),f-字符串有了正式的语法:花括号内可以使用与外层相同的引号、反斜杠和换行,嵌套深度也不再受限。花括号内的错误现在会精确指出位置。在较旧的版本中,应在花括号内使用另一种引号:f"{d['key']}",换行则通过单独的变量或 chr(10) 实现。
多行文本可以使用三引号的 f-字符串:f"""合计:{total}\n条目数:{count}"""。
format() 与 %:旧的写法
在旧代码中可能会遇到 "{}: {}".format(item, price) 和 "%s: %d" % (item, price)。format() 使用的格式说明符与 f-字符串相同。当模板需要与数据分开保存时(例如存放在配置文件中),format() 仍然有用。
解析字符串:实际示例
把上面的方法结合起来。假设文件中的行形如 " 2026-10-16; 咖啡 ; 250,50 \n",需要得到日期、名称和以分为单位的金额。通常的步骤是:先清理两端,按分隔符切分,再清理每个部分,最后转换类型。
line = " 2026-10-16; 咖啡 ; 250,50 \n"
date, item, raw_amount = [p.strip() for p in line.strip().split(";")]
amount_kop = round(float(raw_amount.replace(",", ".")) * 100)
print(date, item, amount_kop) # 2026-10-16 咖啡 25050
print(f"{item:<10}{amount_kop / 100:>10.2f}")
如果分出来的部分不是三个,解包会报错:ValueError: not enough values to unpack 或 too many values to unpack。在真实代码中,应该提前检查这类行,或捕获异常。对于带引号和转义字符的真实 CSV 文件,最好使用标准库的 csv 模块,而不是 split。
字符串的常见错误
- 没有保存方法的结果:不赋值的
s.strip()什么也不改变。 - 对数字列表使用 join — 会得到
TypeError;先用map(str, ...)转换。 - 对 strip 传入子串:参数是字符集合,要去掉前缀应使用
removeprefix()。 - 区分大小写的比较:
"Coffee" == "coffee"为False。 - Windows 路径中的反斜杠:如果没有
r前缀,它们会被当作转义字符。
t-字符串:模板而不是现成的文本
Python 3.14 引入了 t-字符串。它们看起来像 f-字符串,只是前缀为 t,但结果不同:不是现成的字符串,而是 string.templatelib.Template 对象。其中,文本片段(.strings)和插入的值(.values)分别保存。
name = "<script>"
tpl = t"你好,{name}!"
print(tpl.strings) # ('你好,', '!')
print(tpl.values) # ('<script>',)
它的用途在于:库可以在拼接之前获得这些值,并对其进行处理——例如转义 HTML 中的尖括号,或者把参数正确地传入 SQL 查询。f-字符串没有这样的机会,因为它已经完成了拼接。普通输出仍然应该使用 f-字符串。
小结
日常处理字符串,Python 只需要一小组工具:split() 和 join() 负责拆分与组合文本,strip() 清理输入,replace() 替换片段,切片截取子串,f-字符串则以所需格式输出数值。记住字符串的不可变性:方法返回新字符串,必须保存结果。课程的支出记录器项目中,这些字符串操作和 f-字符串会在实践中反复用到。
常见问题
如何获得 Python 字符串的长度?
函数 len(s) 返回字符数。对于中文和表情符号,计算的是 Unicode 字符,而不是字节;字节数可以用 len(s.encode("utf-8")) 获得。
如何把数字转换为字符串,再转换回来?
str(250) 得到 '250';int("250") 和 float("2.5") 则是反向转换。如果字符串不是合法的数字,int() 会抛出 ValueError,因此应该检查输入。
为什么 replace 没有改变我的字符串?
字符串是不可变的,replace 返回的是新字符串。把结果赋值回去:s = s.replace("a", "b")。
如何检查字符串是否为空?
空字符串为假,因此直接写 if not s: 即可。如果字符串可能只包含空白,应检查 if not s.strip():。
t-字符串和 f-字符串有什么区别?
f-字符串立即返回现成的 str,而 t-字符串(Python 3.14+)是一个 Template 对象,其中文本片段与值分开保存。这样就可以安全地为 HTML 和 SQL 转义数据。