6 minutes
字符串操作深入
字符串是 Python 中使用最频繁的数据类型之一。无论是从用户获取输入、读写文件、处理网络数据,还是生成报告,字符串操作无处不在。Python 的字符串处理能力非常强大,掌握好字符串操作能让你在处理文本时事半功倍。
字符串基础
创建字符串
# 四种创建方式
s1 = '单引号字符串'
s2 = "双引号字符串"
s3 = '''三单引号
支持换行'''
s4 = """三双引号
也支持换行"""
print(s1) # 单引号字符串
print(s2) # 双引号字符串
print(s3) # 三单引号\n支持换行
单引号 vs 双引号
两种方式完全等价,选择标准是方便性:
# 字符串本身包含单引号时,用双引号更省事
msg1 = "It's a beautiful day" # 不用转义
msg2 = 'It\'s a beautiful day' # 需要转义
# 字符串本身包含双引号时,用单引号更省事
msg3 = '他说:"你好"'
msg4 = "他说:\"你好\""
字符串索引与切片
索引
Python 字符串支持正索引(从 0 开始)和负索引(从 -1 开始):
text = "Python"
# 正索引(从 0 到 length-1)
print(text[0]) # P
print(text[1]) # y
print(text[5]) # n
# 负索引(从 -1 到 -length)
print(text[-1]) # n(最后一个字符)
print(text[-2]) # o(倒数第二个)
print(text[-6]) # P(第一个字符)
# 索引越界
# print(text[100]) # IndexError: string index out of range
切片(Slicing)
切片是 Python 最强大的特性之一,语法为 [start:stop:step]:
text = "Hello, Python!"
# 基本切片 [start:stop](不包含 stop)
print(text[0:5]) # Hello(索引 0~4)
print(text[7:13]) # Python(索引 7~12)
print(text[:5]) # Hello(省略 start,从开头开始)
print(text[7:]) # Python!(省略 stop,直到结尾)
print(text[:]) # Hello, Python!(复制整个字符串)
# 步长切片 [start:stop:step]
print(text[::2]) # Hlo yhn(每隔一个字符取一个)
print(text[1::2]) # el,Pto!(从索引1开始,每隔一个)
# 负步长(反向)
print(text[::-1]) # !nohtyP ,olleH(反转字符串)
# 切片不会索引越界
print("Hello"[0:100]) # Hello(不会报错)
print("Hello"[100:200]) # (空字符串)
切片技巧汇总
s = "Python编程"
# 常用切片模式
s[:3] # "Pyt" 前三个字符
s[3:] # "hon编程" 从索引3到结尾
s[-3:] # "编程" 最后三个字符
s[:-3] # "Python" 去掉最后三个字符
s[::2] # "Pto编" 偶数位字符
s[1::2] # "yh程" 奇数位字符
s[::-1] # "程编nohtyP" 反转
字符串方法
Python 的字符串类型提供了极其丰富的方法。
大小写转换
text = "Hello, Python!"
print(text.upper()) # HELLO, PYTHON!(全部大写)
print(text.lower()) # hello, python!(全部小写)
print(text.title()) # Hello, Python!(每个单词首字母大写)
print(text.capitalize()) # Hello, python!(首字母大写,其余小写)
print(text.swapcase()) # hELLO, pYTHON!(大小写互换)
# 实际应用:用户输入标准化
user_input = " Admin "
if user_input.strip().lower() == "admin":
print("验证通过")
查找与判断
text = "Hello, Python! Python is great."
# find() - 查找子串位置(找不到返回 -1)
print(text.find("Python")) # 7(第一次出现的位置)
print(text.find("Python", 10)) # 15(从索引10开始找)
print(text.find("Java")) # -1(找不到)
# index() - 类似 find(),但找不到会报错
print(text.index("Python")) # 7
# rfind() - 从右侧开始查找
print(text.rfind("Python")) # 15(最后一次出现的位置)
# count() - 统计出现次数
print(text.count("Python")) # 2
print(text.count("o")) # 3
# startswith() / endswith()
print(text.startswith("Hello")) # True
print(text.endswith("great.")) # True
判断类方法
# isalpha() - 是否全是字母
print("Hello".isalpha()) # True
print("Hello123".isalpha()) # False
print("你好".isalpha()) # True(中文字符也算字母)
# isdigit() - 是否全是数字
print("12345".isdigit()) # True
print("12.34".isdigit()) # False(小数点不是数字)
# isnumeric() - 更广泛的数字判断
print("123".isnumeric()) # True
print("一二三".isnumeric()) # True(中文数字)
# isalnum() - 是否只有字母或数字
print("Hello123".isalnum()) # True
# isspace() - 是否全是空白字符
print(" \t\n".isspace()) # True
# islower() / isupper()
print("hello".islower()) # True
print("HELLO".isupper()) # True
分割与拼接
# split() - 分割字符串
text = "apple,banana,orange"
print(text.split(",")) # ['apple', 'banana', 'orange']
text = "Python is awesome"
print(text.split()) # ['Python', 'is', 'awesome'](默认按空白分割)
# 限制分割次数
print(text.split(" ", 1)) # ['Python', 'is awesome']
# splitlines() - 按换行分割
text = "第一行\n第二行\n第三行"
print(text.splitlines()) # ['第一行', '第二行', '第三行']
# join() - 拼接字符串(split 的反操作)
fruits = ["apple", "banana", "orange"]
print(", ".join(fruits)) # apple, banana, orange
print("".join(fruits)) # applebananaorange
替换与清理
# replace() - 替换子串
text = "我喜欢猫,猫很可爱"
print(text.replace("猫", "狗")) # 我喜欢狗,狗很可爱
print(text.replace("猫", "狗", 1)) # 我喜欢狗,猫很可爱(只替换1次)
# strip() - 去除两端空白
text = " Hello, World! \n"
print(repr(text.strip())) # 'Hello, World!'
print(repr(text.lstrip())) # 'Hello, World! \n'(只去左侧)
print(repr(text.rstrip())) # ' Hello, World!'(只去右侧)
# strip() 可以指定要去除的字符
text = "***Hello***"
print(text.strip("*")) # Hello
# removeprefix() / removesuffix()(Python 3.9+)
text = "https://example.com"
print(text.removeprefix("https://")) # example.com
print(text.removesuffix(".com")) # https://example
填充与对齐
# center() - 居中
print("Python".center(20)) # Python
print("Python".center(20, "-")) # -------Python-------
# ljust() / rjust() - 左/右对齐
print("Python".ljust(10, ".")) # Python....
print("Python".rjust(10, ".")) # ....Python
# zfill() - 用 0 填充(左侧)
print("42".zfill(5)) # 00042
print("-42".zfill(5)) # -0042
# 实际应用:格式化表格输出
headers = ["姓名", "年龄", "城市"]
data = [
["张三", 25, "北京"],
["李四", 30, "上海"],
["王五", 22, "广州"]
]
for row in [headers] + data:
print(f"{row[0].ljust(6)} {str(row[1]).center(6)} {row[2].ljust(6)}")
字符串格式化
f-string(Python 3.6+,推荐)
f-string 是目前最推荐、最强大的字符串格式化方式:
name = "小明"
age = 18
score = 95.567
# 基本用法
print(f"我叫{name},今年{age}岁")
# 我叫小明,今年18岁
# 表达式
print(f"明年我{age + 1}岁") # 明年我19岁
# 格式化数字
print(f"成绩: {score:.1f}") # 成绩: 95.6(保留1位小数)
print(f"比例: {0.12345:.2%}") # 比例: 12.35%(百分比)
print(f"大数: {1000000:,}") # 大数: 1,000,000(千分位)
# 对齐和填充
print(f"|{name:>10}|") # | 小明|(右对齐)
print(f"|{name:<10}|") # |小明 |(左对齐)
print(f"|{name:^10}|") # | 小明 |(居中)
format() 方法
# 按位置
print("{} {} {}".format("Python", "is", "fun")) # Python is fun
print("{1} {0} {2}".format("a", "b", "c")) # b a c
# 按名称
print("{name} is {age} years old".format(
name="Alice", age=25
))
# 用 format 处理模板
template = "尊敬的{name},您的订单{order_id}将于{date}送达"
print(template.format(
name="张三",
order_id="ORD-2026-0001",
date="2026-05-10"
))
传统 % 格式化
C 语言风格的格式化,在老旧代码中常见:
name = "Python"
version = 3.13
print("Hello, %s!" % name) # Hello, Python!
print("%s version %d" % (name, version)) # Python version 3
print("PI = %.2f" % 3.14159) # PI = 3.14
转义字符
# 常用转义序列
print("Hello\nWorld!") # \n 换行
print("Hello\tWorld!") # \t 制表符
print("她说:\"你好\"") # \" 双引号
print('It\'s fine') # \' 单引号
print("C:\\Users\\name") # \\ 反斜杠
print("Hello\rWorld") # \r 回车(覆盖前面的内容)
原始字符串(Raw Strings)
原始字符串中的反斜杠不会被当作转义字符处理,在处理正则表达式和文件路径时特别有用:
# 普通字符串中,\n 会被当作换行
print("C:\new\text.txt")
# 实际输出:
# C:
# ew\text.txt(完全不是想要的)
# 原始字符串(在引号前加 r)
print(r"C:\new\text.txt") # C:\new\text.txt
print(r"Hello\nWorld") # Hello\nWorld(\n 不会换行)
# 正则表达式中的强大作用
import re
pattern = r"\d{3}-\d{4}-\d{4}" # 匹配电话号码
text = "我的电话是 138-1234-5678"
match = re.search(pattern, text)
print(match.group()) # 138-1234-5678
多行字符串
# 使用三引号
long_text = """
这是一个多行字符串。
它可以跨越多行。
"""
print(long_text)
# 使用括号和普通字符串(避免缩进问题)
message = (
"这是一个跨越多行的字符串"
"Python 会自动拼接相邻的字符串字面量"
)
print(message)
# 使用 join 构建多行
lines = ["第一行", "第二行", "第三行"]
text = "\n".join(lines)
print(text)
字符串编码与 Unicode
编码基础
# Python 3 字符串默认使用 Unicode(UTF-8)
text = "Python编程"
# encode() - 编码为字节
utf8_bytes = text.encode("utf-8")
print(utf8_bytes) # b'Python\xe7\xbc\x96\xe7\xa8\x8b'
print(type(utf8_bytes)) # <class 'bytes'>
gbk_bytes = text.encode("gbk")
print(gbk_bytes) # b'Python\xb1\xe0\xb3\xcc'
# decode() - 解码为字符串
print(utf8_bytes.decode("utf-8")) # Python编程
print(gbk_bytes.decode("gbk")) # Python编程
# 编码错误处理
text = "中文"
try:
text.encode("ascii") # 中文无法用 ASCII 编码
except UnicodeEncodeError as e:
print(f"编码错误: {e}")
Unicode 转义
# Unicode 转义
print("\u4e2d\u6587") # 中文
# ord() - 获取字符的 Unicode 码点
print(ord("中")) # 20013
print(ord("A")) # 65
# chr() - 从码点获取字符
print(chr(20013)) # 中
print(chr(65)) # A
字符串长度与字节长度
text = "Python编程"
# 字符长度(人类可读)
print(len(text)) # 8(6个英文字符 + 2个中文字符)
# 字节长度(编码后)
print(len(text.encode("utf-8"))) # 12
print(len(text.encode("gbk"))) # 10
字符串的不可变性
Python 中的字符串是不可变的,这意味着一旦创建就不能修改:
s = "Hello"
# s[0] = "h" # TypeError! 字符串不可变
# 所有的"修改"操作实际上都是创建新字符串
s = s + ", World" # 创建新字符串
print(s) # Hello, World
# 验证不可变性
original = "Python"
modified = original.upper()
print(original) # Python(原字符串不变)
print(modified) # PYTHON(新字符串)
实践练习:文本分析器
# text_analyzer.py
print("=" * 40)
print(" 文本分析器")
print("=" * 40)
text = input("请输入一段文本: ")
if not text.strip():
print("输入为空!")
exit()
print(f"\n--- 基本信息 ---")
print(f"字符数: {len(text)}")
print(f"单词数: {len(text.split())}")
print(f"行数: {len(text.splitlines())}")
print(f"\n--- 字符统计 ---")
print(f"大写字母: {sum(c.isupper() for c in text)}")
print(f"小写字母: {sum(c.islower() for c in text)}")
print(f"数字: {sum(c.isdigit() for c in text)}")
print(f"空格: {sum(c.isspace() for c in text)}")
print(f"其他字符: {sum(not c.isalnum() and not c.isspace() for c in text)}")
# 词频统计(简单版)
print(f"\n--- 词频统计 ---")
words = text.lower().split()
word_freq = {}
for word in words:
word = word.strip(".,!?;:\"'()[]")
if word:
word_freq[word] = word_freq.get(word, 0) + 1
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
for word, count in sorted_words[:10]:
print(f" {word:12s}: {count} 次")
常见陷阱
1. 字符串拼接性能
# 在循环中拼接字符串效率低下(O(n²))
result = ""
for i in range(10000):
result += str(i) # 每次创建新字符串
# 使用 join(O(n))
result = "".join(str(i) for i in range(10000))
# 或者使用列表和 join
parts = []
for i in range(10000):
parts.append(str(i))
result = "".join(parts)
2. 中文字符长度
# Python 中 len() 统计的是字符数,不是字节数
text = "你好世界"
print(len(text)) # 4
# 如果需要字节长度
print(len(text.encode("utf-8"))) # 12
print(len(text.encode("gbk"))) # 8
3. 字符串和数字拼接
# 错误
# print("结果: " + 42) # TypeError
# 正确
print("结果: " + str(42))
print(f"结果: {42}")
小结
在这篇文章中,我们深入学习了 Python 字符串的使用:
- 创建字符串:单引号、双引号、三引号
- 索引与切片:正索引、负索引、步长切片
- 字符串方法:大小写转换、查找、判断、分割、替换、填充等
- 字符串格式化:f-string(推荐)、format()、% 格式化
- 转义字符与原始字符串
- 多行字符串的构建方法
- Unicode 与编码基础
- 字符串的不可变性
下一步
字符串是文本处理的基础。下一篇文章我们将学习列表与元组——Python 中最常用的序列类型,它们能帮我们高效地组织和处理批量数据。
实践建议:打开 Python REPL,创建一个字符串并尝试各种索引和切片操作。特别注意负索引和步长切片的行为。f-string 的各种格式化方式也值得多练练——实际工作中每天都在用。
Summary: 字符串索引切片方法格式化详解。