一、Python 字符串基础

在 Python 3 中,字符串是由 Unicode 码点组成的不可变序列。这是理解所有字符处理的基础。

1. 字符串的创建

使用单引号 '...'、双引号 "..."、三引号 '''...''' 或 """..."""

s1 = 'Hello'
s2 = "World"
s3 = '''这是一个
多行字符串'''

2. 字符串的不可变性

字符串一旦创建,其内容就不能改变。任何“修改”操作都会生成一个新的字符串对象。

s = "apple"
# s[0] = 'b'  # 这会报错:TypeError

# 正确的方式是创建一个新字符串
new_s = 'b' + s[1:]  # new_s 为 "bpple"

3. 原始字符串 (Raw Strings)

在字符串前加 r 或 R,反斜杠 \ 不会被当作转义字符。这在处理正则表达式和文件路径时非常有用。

path = r'C:\Users\Name\Documents' # 不会被解析为转义序列
regex_pattern = r'\d+' # 匹配数字的正则表达式

4. 格式化字符串 (f-Strings) - Python 3.6+

一种非常高效和易读的字符串格式化方法。

name = "Alice"
age = 30
greeting = f"Hello, {name}. You are {age} years old."
# 输出:Hello, Alice. You are 30 years old.

# 可以在表达式内进行计算
message = f"In 5 years, you will be {age + 5}."

二、核心字符串操作与方法

字符串支持所有通用的序列操作(索引、切片、inlen()min()max()),同时还拥有大量内置方法。

1. 查找与替换

  • str.find(sub)str.index(sub):查找子串,返回首次出现的索引。find 找不到返回 -1,index 找不到会抛出 ValueError
  • str.rfind(sub)str.rindex(sub):从右边开始查找。
  • str.replace(old, new[, count]):替换字符串,count 指定替换次数。
s = "hello world"
print(s.find('o'))       # 4
print(s.rfind('o'))      # 7
print(s.replace('l', 'L', 2)) # heLLo world

2. 分割与连接

  • str.split(sep=None, maxsplit=-1):根据分隔符 sep 分割字符串,返回列表。
  • str.rsplit(...):从右边开始分割。
  • str.partition(sep):将字符串分成三部分 (sep之前的部分, sep, sep之后的部分)
  • str.join(iterable):用字符串将可迭代对象中的元素连接起来。
data = "apple,banana,cherry"
fruits = data.split(',')  # ['apple', 'banana', 'cherry']
new_data = '-'.join(fruits) # 'apple-banana-cherry'

# partition 常用于解析字符串
url = "https://www.example.com"
protocol, separator, domain = url.partition('://')

3. 大小写转换

  • str.lower():转为小写。
  • str.upper():转为大写。
  • str.title():每个单词首字母大写。
  • str.capitalize():整个字符串首字母大写。
  • str.swapcase():大小写互换。

4. 判断类方法 (返回布尔值)

  • str.startswith(prefix)str.endswith(suffix):检查开头/结尾。
  • str.isalpha():是否全是字母。
  • str.isdigit():是否全是数字。
  • str.isalnum():是否全是字母或数字。
  • str.isspace():是否全是空白字符。
  • str.islower()str.isupper():检查大小写格式。
"abc123".isalnum() # True
"   ".isspace()    # True
"file.txt".endswith('.txt') # True

5. 去除空白与填充

  • str.strip([chars]):去除两端的指定字符(默认为空白符)。
  • str.lstrip([chars])str.rstrip([chars]):去除左/右端的指定字符。
  • str.center(width[, fillchar]):居中填充。
  • str.ljust(width[, fillchar])str.rjust(width[, fillchar]):左/右对齐填充。
  • str.zfill(width):用 0 在左边填充。
s = "   hello   "
s.strip()    # 'hello'
"42".zfill(5) # '00042'
"hi".center(10, '*') # '****hi****'

三、高级字符处理

1. 正则表达式 (re 模块)

对于复杂的模式匹配、查找和替换,正则表达式是终极武器。

常见场景:

  • 验证:邮箱、电话号码、密码强度。
  • 提取:从日志文件或HTML中提取特定信息。
  • 分割:使用复杂的分隔符(如多个空格、标点符号)。
  • 替换:进行复杂的文本重写。
import re

text = "My phone numbers are 123-456-7890 and (555) 123-4567."

# 查找所有电话号码
# 模式解释:\d 匹配数字,{3} 匹配3次,[...] 匹配括号或空格等
pattern = r'\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}'
phones = re.findall(pattern, text)
print(phones) # ['123-456-7890', '(555) 123-4567']

# 替换,将所有数字替换为 ‘X’
anonymized = re.sub(r'\d', 'X', text)
print(anonymized) # ‘My phone numbers are XXX-XXX-XXXX and (XXX) XXX-XXXX.’

2. 字符串模板 (string.Template)

一种更简单、更安全的字符串替换方式,尤其适合处理用户提供的模板(避免了 % 或 format 可能带来的安全问题)。

from string import Template

t = Template('Hello, $name! Today is $day.')
result = t.substitute(name='Bob', day='Monday')
print(result) # Hello, Bob! Today is Monday.

四、编码与解码 (Bytes & Unicode)

这是处理文件、网络通信和不同数据源时的关键。

  • Unicode:字符串在内存中的表示形式,是一个抽象的字符集。
  • 编码 (Encode):将 str (Unicode) 转换为 bytes(用于存储或传输)。
  • 解码 (Decode):将 bytes 转换回 str (Unicode)。

常见编码: utf-8asciigbklatin-1

# 编码:字符串 -> 字节串
s = "你好,世界"
b = s.encode('utf-8') # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c'

# 解码:字节串 -> 字符串
original_s = b.decode('utf-8') # '你好,世界'

# 处理文件时指定编码
with open('file.txt', 'r', encoding='utf-8') as f:
    content = f.read()
with open('file.txt', 'w', encoding='gbk') as f:
    f.write(content)

处理乱码: 大部分文本处理问题(如乱码)都源于编码和解码时使用的字符集不一致。


五、经典使用场景

数据清洗与预处理

# 清洗用户输入
user_input = "  UsER@Example.COM  \n"
cleaned_input = user_input.strip().lower() # ‘user@example.com‘

# 从CSV行解析数据
csv_line = ‘data1, data2, "data3, with comma", data4‘
# 简单 split(’,’) 会出错,需要使用 csv 模块
import csv
from io import StringIO
reader = csv.reader(StringIO(csv_line))
row = next(reader) # 正确解析出 [’data1‘, ’ data2‘, ’data3, with comma‘, ’ data4‘]

日志分析

log_line = ‘2023-10-27 14:35:21 [ERROR] User login failed for ID: alice‘
# 提取错误级别和时间
parts = log_line.split(’ ‘, 3) # 分割3次
timestamp = parts[0] + ’ ’ + parts[1]
log_level = parts[2].strip(’[]‘)
message = parts[3]

生成动态SQL或HTML

# 使用 f-string 动态生成SQL查询(注意:真实项目应使用参数化查询防止注入!)
table_name = ‘users‘
user_id = 123
query = f“SELECT * FROM {table_name} WHERE id = {user_id}”

URL 解析与构建

# 使用 urllib.parse
from urllib.parse import urlparse, urljoin, urlencode

url = ‘https://www.example.com/path/page?query=python#fragment‘
parsed = urlparse(url)
print(parsed.netloc) # ’www.example.com‘
print(parsed.query)  # ’query=python‘

# 构建查询参数
params = {’q‘: ’python tutorial‘, ’page‘: 2}
query_string = urlencode(params) # ’q=python+tutorial&page=2‘

模板渲染(简易版)

# 一个非常简单的模板引擎
template = “”“
Dear $customer,
Your order #$order_id is now $status.
“””
data = {’customer‘: ’Alice‘, ’order_id‘: ’12345‘, ’status‘: ’shipped‘}
for key, value in data.items():
    template = template.replace(f’${key}‘, str(value))
print(template)

总结与最佳实践

  1. 选择正确的工具
  • 简单查找/替换:用字符串方法 (findreplace)。
  • 复杂模式:用正则表达式 (re 模块)。
  • 固定位置/格式:用切片和 split
  1. 牢记不可变性:大量字符串拼接操作(如在循环中使用 + 或 +=)性能极差。应使用 .join() 方法。
# 错误 (低效)
result = ""
for s in large_list_of_strings:
    result += s

# 正确 (高效)
result = "".join(large_list_of_strings)
  1. 处理编码问题:遵循 “尽早解码,晚点编码” 的原则。在程序内部始终使用 str (Unicode) 类型,只在输入/输出时进行编解码,并明确指定编码格式。
  2. 注意安全性:当字符串内容来自用户输入时,要警惕。不要直接用字符串拼接来生成命令、查询或HTML,应使用参数化查询或专业的模板引擎。