Python & AI Tutorials Logo
Python 编程

6. 实用字符串处理

在第 5 章中,你学习了处理字符串 (string) 的基础: 创建字符串,通过索引和切片访问字符,以及使用基本的字符串方法。现在我们将在这个基础上更进一步,探索在真实 Python 程序中会经常用到的更高级的字符串操作。

本章聚焦于解决日常编程问题的实用字符串操作技巧: 将文本拆分、再组合,创建看起来专业的格式化输出。无论你是在处理用户输入、生成报表、读取数据文件,还是编写任何与文本打交道的程序,这些技能都至关重要。

6.1) 拆分与拼接字符串

文本处理里最常见的任务之一就是把一个字符串拆成更小的片段,或把多个片段组合成一个字符串。Python 为这两种操作都提供了强大的方法。

6.1.1) 使用 split() 拆分字符串

split() 方法会根据一个分隔符 (separator, 也叫 delimiter) 把字符串拆分成由较小字符串组成的列表。这在处理结构化文本时非常有用,例如 CSV 数据、包含多个值的用户输入,或者把句子拆成单词。

按空白字符进行基础拆分:

当你在调用 split() 时不传入任何参数,它会根据任意空白字符(空格、制表符、换行符)进行拆分,并自动从结果中移除空字符串:

python
# split_basic.py
sentence = "Python is a powerful programming language"
words = sentence.split()
print(words)  # Output: ['Python', 'is', 'a', 'powerful', 'programming', 'language']
print(len(words))  # Output: 6

注意 split() 是如何智能地处理多个空格的:

python
# split_whitespace.py
messy_text = "Python    is     awesome"
words = messy_text.split()
print(words)  # Output: ['Python', 'is', 'awesome']

即使单词之间有多个空格,split() 也会把任意数量的空白字符当作单个分隔符来看待,并生成一个干净的列表。

按指定分隔符拆分:

你可以通过传入参数来精确指定要按什么字符或字符串来拆分:

python
# split_separator.py
csv_data = "apple,banana,cherry,date"
fruits = csv_data.split(',')
print(fruits)  # Output: ['apple', 'banana', 'cherry', 'date']
 
date_string = "2024-03-15"
parts = date_string.split('-')
print(parts)  # Output: ['2024', '03', '15']
year = parts[0]
month = parts[1]
day = parts[2]
print(f"Year: {year}, Month: {month}, Day: {day}")  # Output: Year: 2024, Month: 03, Day: 15

重要区别: 当你指定了分隔符时,split() 会按字面意思对待该分隔符,如果分隔符连续出现,就会产生空字符串:

python
# split_empty_strings.py
data = "apple,,cherry"
result = data.split(',')
print(result)  # Output: ['apple', '', 'cherry']
print(len(result))  # Output: 3

中间的空字符串 '' 表示两个连续逗号之间的“空内容”。这种行为与不带参数按空白拆分时不同。

限制拆分次数:

你可以通过传入第二个参数 maxsplit 来控制最多拆分几次:

python
# split_maxsplit.py
text = "one:two:three:four:five"
parts = text.split(':', 2)  # 只在前两个冒号处进行拆分
print(parts)  # Output: ['one', 'two', 'three:four:five']

这样最多会产生 3 个部分 (maxsplit + 1),因为在达到指定拆分次数后就会停止,字符串的剩余部分将保持原样。

实用示例: 处理用户输入

python
# process_input.py
user_input = input("Enter your full name: ")
# 用户输入: "Alice Marie Johnson"
 
name_parts = user_input.split()
if len(name_parts) >= 2:
    first_name = name_parts[0]
    last_name = name_parts[-1]  # 最后一个元素
    print(f"First name: {first_name}")  # Output: First name: Alice
    print(f"Last name: {last_name}")    # Output: Last name: Johnson
else:
    print("Please enter at least a first and last name")

6.1.2) 使用 join() 拼接字符串

join() 方法与 split() 正好相反: 它把一个由字符串组成的列表(或任意可迭代对象)拼接成一个单一字符串,在每个元素之间插入一个分隔符。这个语法一开始可能有点反直觉——是分隔符字符串来调用方法,而列表作为参数传入。

基础拼接:

python
# join_basic.py
words = ['Python', 'is', 'awesome']
sentence = ' '.join(words)
print(sentence)  # Output: Python is awesome
 
csv_line = ','.join(['apple', 'banana', 'cherry'])
print(csv_line)  # Output: apple,banana,cherry

调用 join() 的字符串(比如 ' '',')会作为元素之间的分隔符。

为什么语法是 separator.join(list):

从分隔符的角度思考就能理解这个语法: “我要把这些项目连接起来,并把自己插入到每一对相邻项目之间。”这种写法也便于优雅地链式调用,而且能让分隔符在代码中非常显眼。

使用不同分隔符进行拼接:

python
# join_separators.py
items = ['eggs', 'milk', 'bread', 'butter']
 
# 逗号分隔
print(', '.join(items))  # Output: eggs, milk, bread, butter
 
# 按换行分隔(每个元素一行)
print('\n'.join(items))
# Output:
# eggs
# milk
# bread
# butter
 
# 连字符分隔
print('-'.join(items))  # Output: eggs-milk-bread-butter
 
# 无分隔符(直接连接)
print(''.join(items))  # Output: eggsmilkbreadbutter

重要: join() 只能处理字符串:

可迭代对象中的所有元素都必须是字符串。如果你试图拼接数字或其他类型,会得到错误:

python
# join_error.py
numbers = [1, 2, 3, 4]
# result = ','.join(numbers)  # This would cause: TypeError: sequence item 0: expected str instance, int found

要拼接非字符串元素,需要先把它们转换为字符串。我们将在第 34 章学习一种更优雅的方式,目前你可以手动转换每个元素:

python
# join_numbers.py
numbers = [1, 2, 3, 4]
# 手动把每个数字转换为字符串
string_numbers = [str(numbers[0]), str(numbers[1]), str(numbers[2]), str(numbers[3])]
result = ','.join(string_numbers)
print(result)  # Output: 1,2,3,4

实用示例: 构建文件路径

python
# build_path.py
path_parts = ['home', 'user', 'documents', 'report.txt']
# 在类 Unix 系统上(Linux, macOS)
unix_path = '/'.join(path_parts)
print(unix_path)  # Output: home/user/documents/report.txt
 
# 在 Windows 上
windows_path = '\\'.join(path_parts)
print(windows_path)  # Output: home\user\documents\report.txt

注意: 在第 26 章中,我们将学习 os.path 模块,它提供了更好的跨平台路径处理方式,不过这里足以展示拼接的概念。

6.1.3) 组合 split() 和 join() 进行文本处理

这两个方法配合使用时在文本转换方面非常强大。通过把它们组合起来,你可以清理杂乱输入、在不同格式之间转换、或者提取并重新组织数据:

python
# transform_text.py
# 将多个空格替换为单个空格
messy = "Python    is     really    cool"
clean = ' '.join(messy.split())
print(clean)  # Output: Python is really cool
 
# 将逗号分隔转换为空格分隔
csv_data = "apple,banana,cherry"
space_separated = ' '.join(csv_data.split(','))
print(space_separated)  # Output: apple banana cherry
 
# 移除所有空格
text_with_spaces = "H e l l o"
no_spaces = ''.join(text_with_spaces.split())
print(no_spaces)  # Output: Hello

6.1.4) 其他拆分方法

Python 还针对一些特定场景提供了额外的拆分方法:

rsplit() - 从右侧开始拆分:

python
# rsplit_example.py
path = "folder/subfolder/file.txt"
 
# 使用 maxsplit 的常规 split
parts = path.split('/', 1)
print(parts)  # Output: ['folder', 'subfolder/file.txt']
 
# rsplit 从右侧开始拆分
parts = path.rsplit('/', 1)
print(parts)  # Output: ['folder/subfolder', 'file.txt']

当你希望把字符串中的最后一部分与前面的所有内容分离时,这会很有用。

splitlines() - 按行分隔符拆分:

python
# splitlines_example.py
multiline = "Line 1\nLine 2\nLine 3"
lines = multiline.splitlines()
print(lines)  # Output: ['Line 1', 'Line 2', 'Line 3']
 
# 适配不同风格的行结束符
mixed_lines = "Line 1\nLine 2\r\nLine 3\rLine 4"
all_lines = mixed_lines.splitlines()
print(all_lines)  # Output: ['Line 1', 'Line 2', 'Line 3', 'Line 4']

splitlines() 方法可以识别所有标准的换行约定(\n, \r\n, \r),并据此进行拆分,比使用 split('\n') 在处理来自不同来源的文本时更健壮。

6.2) 使用 f-Strings 格式化字符串

创建格式化输出是编程中最常见的任务之一。你需要把文本和变量值结合起来,对齐列、格式化数字,为用户创建可读的输出。Python 的 f-string(格式化字符串字面量,formatted string literal) 提供了最现代、可读性最高且功能强大的方式来完成这些工作。

6.2.1) f-String 的基本语法

f-string 是以 fF 前缀开头的字符串字面量,它可以在花括号 {} 中包含表达式。Python 会计算这些表达式的值,并把结果转换为字符串:

python
# fstring_basic.py
name = "Alice"
age = 30
greeting = f"Hello, {name}! You are {age} years old."
print(greeting)  # Output: Hello, Alice! You are 30 years old.

花括号 {} 中可以放任意合法的 Python 表达式:

python
# fstring_expressions.py
x = 10
y = 20
result = f"The sum of {x} and {y} is {x + y}"
print(result)  # Output: The sum of 10 and 20 is 30
 
price = 19.99
quantity = 3
total = f"Total cost: ${price * quantity}"
print(total)  # Output: Total cost: $59.97

6.2.2) 为什么 f-Strings 比旧方法更好

在 f-string(在 Python 3.6 中引入)出现之前,程序员通常使用字符串拼接或 format() 方法。我们来做个比较:

字符串拼接(旧的、易出错的方式):

python
# concatenation_example.py
name = "Bob"
age = 25
# 需要手动把数字转换成字符串,并使用大量的 + 运算符
message = "Hello, " + name + "! You are " + str(age) + " years old."
print(message)  # Output: Hello, Bob! You are 25 years old.

这种方式冗长、容易出错(忘记写 str() 就会报错),而且当变量多时难以阅读。

f-string(现代、简洁的方式):

python
# fstring_clean.py
name = "Bob"
age = 25
message = f"Hello, {name}! You are {age} years old."
print(message)  # Output: Hello, Bob! You are 25 years old.

f-string 会自动把值转换为字符串,更易读,而且实际上比其他方式更快。

6.2.3) 在 f-String 中使用表达式和方法调用

你可以在 f-string 中放入复杂的表达式、方法调用甚至函数调用:

python
# fstring_methods.py
name = "alice"
print(f"Capitalized: {name.capitalize()}")  # Output: Capitalized: Alice
print(f"Uppercase: {name.upper()}")  # Output: Uppercase: ALICE
print(f"Length: {len(name)}")  # Output: Length: 5
 
# 算术与比较
x = 10
print(f"Is {x} even? {x % 2 == 0}")  # Output: Is 10 even? True
 
# 索引与切片
text = "Python"
print(f"First letter: {text[0]}")  # Output: First letter: P
print(f"First three: {text[:3]}")  # Output: First three: Pyt

6.2.4) 在 f-Strings 中格式化数字

f-string 支持格式说明符 (format specifier),用来控制值的显示方式。语法是 {expression:format_spec}:

控制浮点数的小数位数:

python
# fstring_decimals.py
pi = 3.14159265359
 
print(f"Default: {pi}")  # Output: Default: 3.14159265359
print(f"2 decimals: {pi:.2f}")  # Output: 2 decimals: 3.14
print(f"4 decimals: {pi:.4f}")  # Output: 4 decimals: 3.1416
print(f"No decimals: {pi:.0f}")  # Output: No decimals: 3

格式说明符 .2f 的意思是“以浮点数形式显示,保留 2 位小数”。f 代表“定点表示法”(fixed-point notation)。

使用千位分隔符:

python
# fstring_thousands.py
large_number = 1234567890
 
print(f"No separator: {large_number}")  # Output: No separator: 1234567890
print(f"With commas: {large_number:,}")  # Output: With commas: 1,234,567,890
print(f"With underscores: {large_number:_}")  # Output: With underscores: 1_234_567_890
 
# 与小数位数组合使用
price = 1234567.89
print(f"Price: ${price:,.2f}")  # Output: Price: $1,234,567.89

百分比格式化:

python
# fstring_percentage.py
ratio = 0.847
print(f"Ratio: {ratio}")  # Output: Ratio: 0.847
print(f"Percentage: {ratio:.1%}")  # Output: Percentage: 84.7%
print(f"Percentage: {ratio:.2%}")  # Output: Percentage: 84.70%

% 格式说明符会把值乘以 100 并添加百分号。

6.2.5) 使用 f-Strings 的实用示例

创建格式化报表:

python
# report_example.py
product = "Laptop"
price = 899.99
quantity = 5
tax_rate = 0.08
 
subtotal = price * quantity
tax = subtotal * tax_rate
total = subtotal + tax
 
print(f"Product: {product}")  # Output: Product: Laptop
print(f"Price: ${price:.2f}")  # Output: Price: $899.99
print(f"Quantity: {quantity}")  # Output: Quantity: 5
print(f"Subtotal: ${subtotal:.2f}")  # Output: Subtotal: $4499.95
print(f"Tax (8%): ${tax:.2f}")  # Output: Tax (8%): $360.00
print(f"Total: ${total:.2f}")  # Output: Total: $4859.95

创建用户友好的消息:

python
# user_messages.py
username = "Alice"
login_count = 42
last_login = "2024-03-15"
 
welcome = f"Welcome back, {username}!"
stats = f"You've logged in {login_count} times. Last login: {last_login}"
 
print(welcome)  # Output: Welcome back, Alice!
print(stats)  # Output: You've logged in 42 times. Last login: 2024-03-15

6.2.6) 使用 f-Strings 进行调试

Python 3.8 引入了用于调试的 = 说明符,它会同时显示表达式和其值:

python
# fstring_debug.py
x = 10
y = 20
z = x + y
 
print(f"{x=}")  # Output: x=10
print(f"{y=}")  # Output: y=20
print(f"{z=}")  # Output: z=30
print(f"{x + y=}")  # Output: x + y=30

在开发过程中,这对快速检查变量值非常有用,而且不必把变量名写两遍。

6.2.7) 在 f-Strings 中转义花括号

如果你需要在 f-string 中输出字面量花括号,请将其写成双重花括号:

python
# fstring_escape.py
value = 42
# 单个花括号是表达式占位符
print(f"Value: {value}")  # Output: Value: 42
 
# 双花括号会输出字面量花括号
print(f"Use {{value}} as a placeholder")  # Output: Use {value} as a placeholder
print(f"The value is {value}, shown as {{value}}")  # Output: The value is 42, shown as {value}

6.3) 使用 format() 和格式说明符进行格式化

虽然 f-string 是现代推荐方式,但 format() 方法仍被广泛使用,并提供了一些有用的能力。同时,f-string 也是在 format() 的基础上构建的,因此理解 format() 有助于你更好地理解 f-string。

6.3.1) format() 的基本语法

format() 方法在字符串中使用花括号 {} 作为占位符,待插入的值通过参数传入:

python
# format_basic.py
template = "Hello, {}! You are {} years old."
message = template.format("Alice", 30)
print(message)  # Output: Hello, Alice! You are 30 years old.
 
# 多次使用 format()
greeting = "Hello, {}!".format("Bob")
print(greeting)  # Output: Hello, Bob!

6.3.2) 位置参数与关键字参数

你可以使用位置编号或名称来控制哪个参数放在哪个位置:

位置参数:

python
# format_positional.py
# 默认顺序(0, 1, 2, ...)
template = "{} + {} = {}"
result = template.format(5, 3, 8)
print(result)  # Output: 5 + 3 = 8
 
# 显式位置
template = "{0} + {1} = {2}"
result = template.format(5, 3, 8)
print(result)  # Output: 5 + 3 = 8
 
# 重新排序与重用
template = "{2} = {0} + {1}"
result = template.format(5, 3, 8)
print(result)  # Output: 8 = 5 + 3
 
# 重用同一个值
template = "{0} times {0} equals {1}"
result = template.format(7, 49)
print(result)  # Output: 7 times 7 equals 49

关键字参数:

python
# format_keyword.py
template = "Hello, {name}! You are {age} years old."
message = template.format(name="Alice", age=30)
print(message)  # Output: Hello, Alice! You are 30 years old.
 
# 可以与位置参数混用(位置参数必须在前)
template = "{0}, your score is {score} out of {1}"
result = template.format("Alice", 100, score=95)
print(result)  # Output: Alice, your score is 95 out of 100

6.3.3) 在 format() 中使用格式说明符

格式说明符在 format() 中与在 f-string 中的用法相同,都使用 : 作为分隔符:

python
# format_specifiers.py
pi = 3.14159265359
 
print("{:.2f}".format(pi))  # Output: 3.14
print("{:.4f}".format(pi))  # Output: 3.1416
 
# 使用名称
print("{value:.2f}".format(value=pi))  # Output: 3.14
 
# 多个值使用不同格式
template = "{name}'s score is {score:.1f}%"
result = template.format(name="Bob", score=87.654)
print(result)  # Output: Bob's score is 87.7%

6.3.4) 何时使用 format() 而不是 f-Strings

通常推荐使用 f-string,但在某些特定场景下 format() 更适用:

1. 模板字符串与数据分离定义:

python
# format_templates.py
# 模板定义一次,可用不同数据重复使用
email_template = "Dear {name},\n\nYour order #{order_id} has shipped.\n\nThank you!"
 
# 使用该模板为不同客户生成内容
message1 = email_template.format(name="Alice", order_id=12345)
message2 = email_template.format(name="Bob", order_id=12346)
 
print(message1)
# Output:
# Dear Alice,
#
# Your order #12345 has shipped.
#
# Thank you!
 
print(message2)
# Output:
# Dear Bob,
#
# Your order #12346 has shipped.
#
# Thank you!

2. 模板来自外部来源时:

python
# format_external.py
# 模板可能来自配置文件或数据库
# (我们将在第 24 章学习如何读取文件)
user_template = input("Enter message template: ")
# 用户输入: "Hello, {name}! Welcome to {place}."
 
message = user_template.format(name="Charlie", place="Python")
print(message)  # Output: Hello, Charlie! Welcome to Python.

使用 f-string 时,模板必须写在代码中,因为表达式会立即被求值。而使用 format(),模板可以是来自任意地方的普通字符串。

6.3.5) 访问对象属性和字典键

format() 方法可以直接访问对象属性和字典键:

python
# format_access.py
# 访问字典
person = {"name": "Alice", "age": 30, "city": "Boston"}
message = "Name: {0[name]}, Age: {0[age]}, City: {0[city]}".format(person)
print(message)  # Output: Name: Alice, Age: 30, City: Boston
 
# 使用关键字参数
message = "{p[name]} is {p[age]} years old".format(p=person)
print(message)  # Output: Alice is 30 years old

注意: 我们将在第 30 章学习对象属性,这里只是演示 format() 能够访问嵌套数据结构。

6.4) 在格式化输出中对齐与舍入数字

要让输出看起来更专业,通常需要仔细地控制对齐方式和数字格式。f-string 和 format() 都提供了强大的工具来创建格式良好的表格、报表和展示内容。

6.4.1) 文本对齐

你可以使用格式说明符控制值的宽度与对齐方式:

python
# alignment_basic.py
# 语法: {value:width}
# 默认情况下,字符串左对齐,数字右对齐
 
name = "Alice"
print(f"|{name}|")      # Output: |Alice|
print(f"|{name:10}|")   # Output: |Alice     |  (左对齐,宽度 10)
print(f"|{name:>10}|")  # Output: |     Alice|  (右对齐)
print(f"|{name:^10}|")  # Output: |  Alice   |  (居中对齐)

对齐说明符为:

  • < : 左对齐(字符串默认)
  • > : 右对齐(数字默认)
  • ^ : 居中对齐

数字对齐:

python
# alignment_numbers.py
value = 42
print(f"|{value}|")      # Output: |42|
print(f"|{value:5}|")    # Output: |   42|  (默认右对齐)
print(f"|{value:<5}|")   # Output: |42   |  (左对齐)
print(f"|{value:^5}|")   # Output: | 42  |  (居中对齐)

6.4.2) 自定义填充字符

你可以指定用于填充空白的字符:

python
# alignment_fill.py
name = "Bob"
print(f"|{name:*<10}|")  # Output: |Bob*******|
print(f"|{name:*>10}|")  # Output: |*******Bob|
print(f"|{name:*^10}|")  # Output: |***Bob****|
 
# 用于创建视觉分隔线
print(f"{name:=^20}")    # Output: ========Bob=========

语法是 {value:fill_char align width}

6.4.3) 结合对齐与数字格式化

你可以同时指定宽度、对齐方式和数字格式:

python
# alignment_combined.py
price = 19.99
quantity = 5
total = price * quantity
 
# 右对齐,宽度 10,保留 2 位小数
print(f"Price:    ${price:>10.2f}")     # Output: Price:    $     19.99
print(f"Quantity: {quantity:>10}")      # Output: Quantity:          5
print(f"Total:    ${total:>10.2f}")     # Output: Total:    $     99.95
 
# 使用填充字符实现视觉效果
print(f"Total:    ${total:>10.2f}".replace(' ', '.'))  # Output: Total:....$.....99.95

在本章中,你学习了在几乎所有 Python 程序中都会用到的关键字符串操作技巧: 使用拆分和拼接来进行文本处理,使用 f-string 和格式说明符创建格式化输出,以及对齐和格式化数字以生成专业的展示效果。

这些技能构成了在 Python 中处理文本数据的基础。现在你可以处理用户输入、创建格式化报表、以及处理来自文件的数据(我们将在第 24 章中介绍)。在接下来的 Python 学习过程中,你会不断使用这些字符串处理技巧,所以要多加练习,直到它们变成你的本能。

© 2025. Primesoft Co., Ltd.
support@primesoft.ai