005-字符串处理详解
🟢 难度: 初级 | ⏱️ 预计时间: 4小时 | 📋 前置: 004-运算符与表达式
学习目标
完成本章节后,你将能够:
- 深入理解Python字符串的特性和内部机制
- 掌握字符串的创建、访问和修改方法
- 熟练使用字符串的各种内置方法
- 学会字符串格式化的多种方式
- 理解字符编码和Unicode处理
- 掌握正则表达式在字符串处理中的应用
- 具备处理复杂文本数据的能力
字符串基础
字符串的特性
mindmap
root((Python字符串))
基本特性
不可变性
序列类型
Unicode支持
内存优化
创建方式
单引号
双引号
三引号
原始字符串
格式化字符串
操作类型
索引访问
切片操作
连接拼接
重复操作
成员检查
内置方法
查找方法
替换方法
分割方法
格式化方法
验证方法
字符串的创建方式
print("=== 字符串创建方式 ===")
# 1. 基本创建方式
single_quote = 'Hello World'
double_quote = "Hello World"
print(f"单引号: {single_quote}")
print(f"双引号: {double_quote}")
print(f"相等性: {single_quote == double_quote}") # True
# 2. 三引号字符串(多行)
multiline_string = '''这是一个
多行字符串
可以包含换行符'''
docstring = """这通常用作
文档字符串
或长文本"""
print(f"\n多行字符串:\n{multiline_string}")
print(f"\n文档字符串:\n{docstring}")
# 3. 原始字符串(Raw String)
regular_path = "C:\\Users\\name\\file.txt" # 需要转义
raw_path = r"C:\Users\name\file.txt" # 原始字符串
regex_pattern = r"\d+\.\d+" # 正则表达式常用
print(f"\n普通字符串: {regular_path}")
print(f"原始字符串: {raw_path}")
print(f"正则模式: {regex_pattern}")
# 4. 格式化字符串(f-string,Python 3.6+)
name = "张三"
age = 25
f_string = f"我叫{name},今年{age}岁"
print(f"\nf-string: {f_string}")
# 5. 字节字符串
byte_string = b"Hello World"
unicode_string = "Hello 世界"
print(f"\n字节字符串: {byte_string}")
print(f"字节字符串类型: {type(byte_string)}")
print(f"Unicode字符串: {unicode_string}")
print(f"Unicode字符串类型: {type(unicode_string)}")
字符串的不可变性
print("=== 字符串不可变性演示 ===")
# 字符串是不可变的
original = "Hello"
print(f"原始字符串: {original}")
print(f"原始字符串ID: {id(original)}")
# 尝试"修改"字符串实际上创建了新字符串
modified = original + " World"
print(f"修改后字符串: {modified}")
print(f"修改后字符串ID: {id(modified)}")
print(f"原始字符串是否改变: {original}")
# 字符串驻留(String Interning)
str1 = "hello"
str2 = "hello"
str3 = "hel" + "lo"
print(f"\n=== 字符串驻留 ===")
print(f"str1 is str2: {str1 is str2}") # True
print(f"str1 is str3: {str1 is str3}") # 可能为True(取决于Python实现)
print(f"str1 == str3: {str1 == str3}") # True
# 大字符串不会被驻留
large_str1 = "a" * 1000
large_str2 = "a" * 1000
print(f"大字符串 is 比较: {large_str1 is large_str2}") # False
print(f"大字符串 == 比较: {large_str1 == large_str2}") # True
字符串索引和切片
索引访问
print("=== 字符串索引访问 ===")
text = "Python编程"
print(f"字符串: {text}")
print(f"长度: {len(text)}")
# 正向索引
print(f"\n=== 正向索引 ===")
for i in range(len(text)):
print(f"索引 {i}: '{text[i]}'")
# 负向索引
print(f"\n=== 负向索引 ===")
for i in range(-len(text), 0):
print(f"索引 {i}: '{text[i]}'")
# 索引边界检查
print(f"\n=== 索引边界 ===")
try:
char = text[100] # 超出范围
except IndexError as e:
print(f"索引错误: {e}")
# 安全的索引访问
def safe_get_char(string, index, default=''):
"""安全获取字符串中的字符"""
try:
return string[index]
except IndexError:
return default
print(f"安全访问索引100: '{safe_get_char(text, 100, '?')}'")
print(f"安全访问索引0: '{safe_get_char(text, 0)}'")
切片操作
print("=== 字符串切片操作 ===")
text = "Python编程语言"
print(f"原字符串: {text}")
# 基本切片
print(f"\n=== 基本切片 ===")
print(f"text[0:6]: '{text[0:6]}'")
print(f"text[6:]: '{text[6:]}'")
print(f"text[:6]: '{text[:6]}'")
print(f"text[:]: '{text[:]}'")
# 负索引切片
print(f"\n=== 负索引切片 ===")
print(f"text[-2:]: '{text[-2:]}'")
print(f"text[:-2]: '{text[:-2]}'")
print(f"text[-4:-2]: '{text[-4:-2]}'")
# 步长切片
print(f"\n=== 步长切片 ===")
print(f"text[::2]: '{text[::2]}'")
print(f"text[1::2]: '{text[1::2]}'")
print(f"text[::-1]: '{text[::-1]}'")
print(f"text[::3]: '{text[::3]}'")
# 实用切片技巧
print(f"\n=== 实用技巧 ===")
# 字符串反转
reversed_text = text[::-1]
print(f"字符串反转: '{reversed_text}'")
# 获取偶数位置字符
even_chars = text[::2]
print(f"偶数位置字符: '{even_chars}'")
# 获取奇数位置字符
odd_chars = text[1::2]
print(f"奇数位置字符: '{odd_chars}'")
# 去除首尾字符
if len(text) > 2:
middle = text[1:-1]
print(f"去除首尾: '{middle}'")
# 切片的边界安全性
print(f"\n=== 切片边界安全 ===")
short_text = "Hi"
print(f"短字符串: '{short_text}'")
print(f"超范围切片: '{short_text[0:100]}'")
print(f"负超范围切片: '{short_text[-100:100]}'")
高级切片应用
class StringSlicer:
"""字符串切片工具类"""
@staticmethod
def get_words(text, word_length=None):
"""按指定长度提取单词"""
if word_length is None:
return text.split()
words = []
for i in range(0, len(text), word_length):
word = text[i:i + word_length]
if word.strip(): # 忽略空白
words.append(word)
return words
@staticmethod
def extract_pattern(text, start_pattern, end_pattern):
"""提取两个模式之间的内容"""
start_idx = text.find(start_pattern)
if start_idx == -1:
return None
start_idx += len(start_pattern)
end_idx = text.find(end_pattern, start_idx)
if end_idx == -1:
return text[start_idx:]
return text[start_idx:end_idx]
@staticmethod
def chunk_string(text, chunk_size):
"""将字符串分块"""
return [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]
@staticmethod
def interleave_strings(str1, str2):
"""交错合并两个字符串"""
result = []
max_len = max(len(str1), len(str2))
for i in range(max_len):
if i < len(str1):
result.append(str1[i])
if i < len(str2):
result.append(str2[i])
return ''.join(result)
# 测试字符串切片工具
print("=== 字符串切片工具测试 ===")
slicer = StringSlicer()
# 测试按长度提取
text = "Hello World Python Programming"
print(f"原文本: {text}")
print(f"按5字符分组: {slicer.get_words(text, 5)}")
print(f"按单词分组: {slicer.get_words(text)}")
# 测试模式提取
html_text = "<div>这是内容</div><span>另一个内容</span>"
print(f"\nHTML文本: {html_text}")
div_content = slicer.extract_pattern(html_text, "<div>", "</div>")
span_content = slicer.extract_pattern(html_text, "<span>", "</span>")
print(f"div内容: {div_content}")
print(f"span内容: {span_content}")
# 测试字符串分块
long_text = "这是一个很长的字符串需要分块处理"
print(f"\n长文本: {long_text}")
chunks = slicer.chunk_string(long_text, 4)
print(f"分块结果: {chunks}")
# 测试交错合并
str1 = "ACE"
str2 = "BDF"
print(f"\n字符串1: {str1}")
print(f"字符串2: {str2}")
interleaved = slicer.interleave_strings(str1, str2)
print(f"交错结果: {interleaved}")
字符串方法详解
查找和检查方法
print("=== 字符串查找和检查方法 ===")
text = "Python是一种强大的编程语言,Python很受欢迎"
print(f"测试文本: {text}")
# 查找方法
print(f"\n=== 查找方法 ===")
print(f"find('Python'): {text.find('Python')}") # 返回第一个匹配的索引
print(f"find('Java'): {text.find('Java')}") # 找不到返回-1
print(f"rfind('Python'): {text.rfind('Python')}") # 从右边查找
print(f"index('Python'): {text.index('Python')}") # 类似find,但找不到会抛异常
# 计数方法
print(f"\n=== 计数方法 ===")
print(f"count('Python'): {text.count('Python')}") # 统计出现次数
print(f"count('的'): {text.count('的')}") # 统计中文字符
print(f"count('a'): {text.count('a')}") # 统计字母
# 检查方法
print(f"\n=== 检查方法 ===")
print(f"startswith('Python'): {text.startswith('Python')}") # 检查开头
print(f"endswith('欢迎'): {text.endswith('欢迎')}") # 检查结尾
print(f"'编程' in text: {'编程' in text}") # 成员检查
# 高级查找
print(f"\n=== 高级查找 ===")
# 查找所有匹配位置
def find_all(text, substring):
"""查找所有匹配位置"""
positions = []
start = 0
while True:
pos = text.find(substring, start)
if pos == -1:
break
positions.append(pos)
start = pos + 1
return positions
positions = find_all(text, 'Python')
print(f"'Python'的所有位置: {positions}")
# 查找多个子串
def find_any(text, substrings):
"""查找多个子串中最先出现的"""
earliest_pos = len(text)
found_substring = None
for substring in substrings:
pos = text.find(substring)
if pos != -1 and pos < earliest_pos:
earliest_pos = pos
found_substring = substring
return (earliest_pos, found_substring) if found_substring else (-1, None)
result = find_any(text, ['Java', '编程', '语言'])
print(f"最先出现的子串: 位置{result[0]}, 内容'{result[1]}'")
字符串验证方法
print("=== 字符串验证方法 ===")
# 测试字符串
test_strings = [
"123",
"abc",
"ABC",
"Hello123",
"hello world",
"HELLO WORLD",
" ",
"",
"Hello World",
"hello_world",
"123.45",
"\t\n",
"你好世界"
]
print(f"{'字符串':<15} {'数字':<8} {'字母':<8} {'字母数字':<10} {'小写':<8} {'大写':<8} {'空白':<8} {'标题':<8}")
print("-" * 80)
for s in test_strings:
display_s = repr(s) if len(s) < 10 else repr(s[:7] + '...')
print(f"{display_s:<15} {str(s.isdigit()):<8} {str(s.isalpha()):<8} {str(s.isalnum()):<10} "
f"{str(s.islower()):<8} {str(s.isupper()):<8} {str(s.isspace()):<8} {str(s.istitle()):<8}")
# 详细验证方法说明
print(f"\n=== 验证方法详解 ===")
test_cases = {
'isdigit()': ['123', '0', '007', '12.3', '-123'],
'isalpha()': ['abc', 'ABC', 'Hello', '123', 'hello123'],
'isalnum()': ['abc123', 'Hello', '123', 'hello world', 'test_case'],
'islower()': ['hello', 'HELLO', 'Hello', 'hello123', 'hello world'],
'isupper()': ['HELLO', 'hello', 'Hello', 'HELLO123', 'HELLO WORLD'],
'isspace()': [' ', '\t\n', ' ', 'hello', ''],
'istitle()': ['Hello World', 'hello world', 'HELLO WORLD', 'Hello', 'Hello123']
}
for method, test_values in test_cases.items():
print(f"\n{method}:")
for value in test_values:
result = getattr(value, method.replace('()', ''))()
print(f" '{value}' -> {result}")
字符串转换方法
print("=== 字符串转换方法 ===")
original = "Hello World Python Programming"
print(f"原始字符串: {original}")
# 大小写转换
print(f"\n=== 大小写转换 ===")
print(f"lower(): {original.lower()}")
print(f"upper(): {original.upper()}")
print(f"capitalize(): {original.capitalize()}")
print(f"title(): {original.title()}")
print(f"swapcase(): {original.swapcase()}")
# 特殊情况处理
special_text = "hello WORLD 123 测试"
print(f"\n特殊文本: {special_text}")
print(f"casefold(): {special_text.casefold()}") # 更强的小写转换
# 去除空白
whitespace_text = " Hello World \t\n"
print(f"\n=== 去除空白 ===")
print(f"原文本: {repr(whitespace_text)}")
print(f"strip(): {repr(whitespace_text.strip())}")
print(f"lstrip(): {repr(whitespace_text.lstrip())}")
print(f"rstrip(): {repr(whitespace_text.rstrip())}")
# 自定义去除字符
custom_text = "...Hello World..."
print(f"\n自定义去除: {custom_text}")
print(f"strip('.'): {custom_text.strip('.')}")
print(f"strip('.H'): {custom_text.strip('.H')}")
# 填充和对齐
print(f"\n=== 填充和对齐 ===")
text = "Python"
width = 20
print(f"原文本: '{text}'")
print(f"center({width}): '{text.center(width)}'")
print(f"ljust({width}): '{text.ljust(width)}'")
print(f"rjust({width}): '{text.rjust(width)}'")
print(f"center({width}, '*'): '{text.center(width, '*')}'")
print(f"zfill(10): '{text.zfill(10)}'")
# 数字填充
number = "42"
print(f"\n数字填充: '{number}'")
print(f"zfill(5): '{number.zfill(5)}'")
print(f"rjust(5, '0'): '{number.rjust(5, '0')}'")
字符串分割和连接
print("=== 字符串分割和连接 ===")
# 基本分割
text = "apple,banana,orange,grape"
print(f"原文本: {text}")
print(f"split(','): {text.split(',')}")
print(f"split(',', 2): {text.split(',', 2)}") # 限制分割次数
# 空白分割
whitespace_text = "apple banana\tgrape\norange"
print(f"\n空白文本: {repr(whitespace_text)}")
print(f"split(): {whitespace_text.split()}") # 默认按空白分割
# 行分割
multiline = "第一行\n第二行\r\n第三行\r第四行"
print(f"\n多行文本: {repr(multiline)}")
print(f"splitlines(): {multiline.splitlines()}")
print(f"splitlines(True): {multiline.splitlines(True)}") # 保留换行符
# 分区操作
url = "https://www.example.com/path"
print(f"\nURL: {url}")
scheme, sep, rest = url.partition('://')
print(f"partition('://'): ('{scheme}', '{sep}', '{rest}')")
host, sep, path = rest.partition('/')
print(f"partition('/'): ('{host}', '{sep}', '{path}')")
# 右分区
email = "user@example.com"
print(f"\nEmail: {email}")
user, sep, domain = email.rpartition('@')
print(f"rpartition('@'): ('{user}', '{sep}', '{domain}')")
# 字符串连接
print(f"\n=== 字符串连接 ===")
words = ['Python', 'is', 'awesome']
print(f"单词列表: {words}")
print(f"join(' '): '{' '.join(words)}'")
print(f"join('-'): '{'-'.join(words)}'")
print(f"join(''): '{'.join(words)}'")
# 连接不同类型
numbers = [1, 2, 3, 4, 5]
print(f"\n数字列表: {numbers}")
number_strings = [str(n) for n in numbers]
print(f"转换为字符串: {number_strings}")
print(f"连接结果: '{','.join(number_strings)}'")
# 高级分割应用
class TextProcessor:
"""文本处理器"""
@staticmethod
def smart_split(text, delimiters=None):
"""智能分割,支持多个分隔符"""
if delimiters is None:
delimiters = [',', ';', '|', '\t']
# 找到第一个存在的分隔符
for delimiter in delimiters:
if delimiter in text:
return text.split(delimiter)
# 如果没有找到分隔符,按空白分割
return text.split()
@staticmethod
def extract_quoted_strings(text):
"""提取引号中的字符串"""
import re
# 匹配单引号或双引号中的内容
pattern = r'["\']([^"\']*)["\']
matches = re.findall(pattern, text)
return matches
@staticmethod
def split_preserve_quotes(text, delimiter=','):
"""分割时保留引号内的内容"""
import csv
import io
# 使用CSV模块处理引号
reader = csv.reader(io.StringIO(text), delimiter=delimiter)
return next(reader)
# 测试文本处理器
processor = TextProcessor()
print(f"\n=== 高级分割测试 ===")
# 智能分割测试
test_texts = [
"apple,banana,orange",
"apple;banana;orange",
"apple|banana|orange",
"apple\tbanana\torange",
"apple banana orange"
]
for test_text in test_texts:
result = processor.smart_split(test_text)
print(f"'{test_text}' -> {result}")
# 引号提取测试
quoted_text = 'He said "Hello World" and she replied \'Hi there\''
print(f"\n引号文本: {quoted_text}")
quoted_strings = processor.extract_quoted_strings(quoted_text)
print(f"提取结果: {quoted_strings}")
# CSV风格分割
csv_text = 'apple,"banana, with comma",orange'
print(f"\nCSV文本: {csv_text}")
csv_result = processor.split_preserve_quotes(csv_text)
print(f"CSV分割: {csv_result}")
字符串格式化
传统格式化方法
print("=== 传统字符串格式化 ===")
# % 格式化(C风格)
name = "张三"
age = 25
score = 95.5
print(f"=== % 格式化 ===")
print("姓名: %s, 年龄: %d" % (name, age))
print("姓名: %s, 年龄: %d, 分数: %.2f" % (name, age, score))
print("分数: %06.2f" % score) # 零填充
print("十六进制: %x, 八进制: %o" % (255, 255))
# 字典格式化
user_info = {'name': '李四', 'age': 30, 'city': '北京'}
print("\n字典格式化:")
print("%(name)s来自%(city)s,今年%(age)d岁" % user_info)
# format() 方法
print(f"\n=== format() 方法 ===")
print("姓名: {}, 年龄: {}".format(name, age))
print("姓名: {0}, 年龄: {1}, 再次提到{0}".format(name, age))
print("姓名: {name}, 年龄: {age}".format(name=name, age=age))
# 格式化规范
print(f"\n=== 格式化规范 ===")
pi = 3.14159265359
print("π = {:.2f}".format(pi)) # 保留2位小数
print("π = {:.6f}".format(pi)) # 保留6位小数
print("π = {:10.2f}".format(pi)) # 宽度10,保留2位小数
print("π = {:0>10.2f}".format(pi)) # 右对齐,零填充
print("π = {:^15.2f}".format(pi)) # 居中对齐
# 数字格式化
number = 1234567
print(f"\n数字格式化:")
print("千分位: {:,}".format(number))
print("百分比: {:.2%}".format(0.1234))
print("科学计数法: {:e}".format(number))
print("二进制: {:b}".format(255))
print("十六进制: {:x}".format(255))
print("八进制: {:o}".format(255))
f-string 格式化(推荐)
import datetime
import math
print("=== f-string 格式化 ===")
# 基本用法
name = "王五"
age = 28
height = 175.5
print(f"基本信息: {name}, {age}岁, {height}cm")
# 表达式计算
print(f"明年{name}将{age + 1}岁")
print(f"BMI计算需要体重,身高{height}cm")
print(f"数学计算: 2 + 3 = {2 + 3}")
print(f"字符串操作: {name.upper()}")
# 格式化规范
pi = math.pi
print(f"\n=== f-string 格式化规范 ===")
print(f"π = {pi:.2f}") # 保留2位小数
print(f"π = {pi:10.4f}") # 宽度10,保留4位小数
print(f"π = {pi:0>12.4f}") # 零填充,右对齐
print(f"π = {pi:^15.4f}") # 居中对齐
# 数字格式化
big_number = 1234567890
percentage = 0.8765
print(f"\n数字格式化:")
print(f"千分位: {big_number:,}")
print(f"百分比: {percentage:.2%}")
print(f"科学计数法: {big_number:.2e}")
print(f"十六进制: {255:x}")
print(f"二进制: {255:b}")
# 日期时间格式化
now = datetime.datetime.now()
print(f"\n日期时间格式化:")
print(f"当前时间: {now}")
print(f"格式化时间: {now:%Y-%m-%d %H:%M:%S}")
print(f"中文格式: {now:%Y年%m月%d日}")
# 调试格式化(Python 3.8+)
import sys
if sys.version_info >= (3, 8):
x = 10
y = 20
print(f"\n调试格式化:")
print(f"{x=}, {y=}")
print(f"{x + y=}")
print(f"{math.sqrt(x)=:.2f}")
# 复杂格式化
data = {
'name': '赵六',
'scores': [85, 92, 78, 96],
'info': {'age': 22, 'major': '计算机科学'}
}
print(f"\n复杂数据格式化:")
print(f"学生: {data['name']}")
print(f"年龄: {data['info']['age']}岁")
print(f"专业: {data['info']['major']}")
print(f"平均分: {sum(data['scores'])/len(data['scores']):.1f}")
print(f"最高分: {max(data['scores'])}")
print(f"分数列表: {', '.join(map(str, data['scores']))}")
高级格式化技巧
class AdvancedFormatter:
"""高级格式化工具类"""
@staticmethod
def format_table(data, headers=None, align='left'):
"""格式化表格数据"""
if not data:
return ""
# 确定列宽
if headers:
all_data = [headers] + data
else:
all_data = data
col_widths = []
for col in range(len(all_data[0])):
max_width = max(len(str(row[col])) for row in all_data)
col_widths.append(max_width)
# 格式化函数
def format_row(row, widths, alignment='left'):
formatted_cells = []
for cell, width in zip(row, widths):
cell_str = str(cell)
if alignment == 'left':
formatted_cells.append(cell_str.ljust(width))
elif alignment == 'right':
formatted_cells.append(cell_str.rjust(width))
else: # center
formatted_cells.append(cell_str.center(width))
return ' | '.join(formatted_cells)
# 生成表格
lines = []
if headers:
lines.append(format_row(headers, col_widths, 'center'))
lines.append('-' * len(lines[0]))
for row in data:
lines.append(format_row(row, col_widths, align))
return '\n'.join(lines)
@staticmethod
def format_bytes(bytes_value):
"""格式化字节大小"""
units = ['B', 'KB', 'MB', 'GB', 'TB']
size = float(bytes_value)
unit_index = 0
while size >= 1024 and unit_index < len(units) - 1:
size /= 1024
unit_index += 1
if unit_index == 0:
return f"{int(size)} {units[unit_index]}"
else:
return f"{size:.2f} {units[unit_index]}"
@staticmethod
def format_duration(seconds):
"""格式化时间长度"""
if seconds < 60:
return f"{seconds:.1f}秒"
elif seconds < 3600:
minutes = seconds // 60
remaining_seconds = seconds % 60
return f"{int(minutes)}分{remaining_seconds:.0f}秒"
else:
hours = seconds // 3600
remaining_minutes = (seconds % 3600) // 60
return f"{int(hours)}小时{int(remaining_minutes)}分钟"
@staticmethod
def format_progress_bar(current, total, width=50, fill='█', empty='░'):
"""格式化进度条"""
if total == 0:
percentage = 0
else:
percentage = current / total
filled_width = int(width * percentage)
bar = fill * filled_width + empty * (width - filled_width)
return f"[{bar}] {percentage:.1%} ({current}/{total})"
@staticmethod
def format_money(amount, currency='¥'):
"""格式化货币"""
return f"{currency}{amount:,.2f}"
# 测试高级格式化
formatter = AdvancedFormatter()
print("=== 高级格式化测试 ===")
# 表格格式化
print("=== 表格格式化 ===")
headers = ['姓名', '年龄', '分数', '等级']
student_data = [
['张三', 20, 95.5, 'A'],
['李四', 21, 87.2, 'B'],
['王五', 19, 92.8, 'A'],
['赵六', 22, 78.5, 'C']
]
table = formatter.format_table(student_data, headers, 'center')
print(table)
# 字节格式化
print(f"\n=== 字节格式化 ===")
byte_sizes = [512, 1024, 1536, 1048576, 1073741824, 1099511627776]
for size in byte_sizes:
formatted = formatter.format_bytes(size)
print(f"{size:>12} bytes = {formatted}")
# 时间格式化
print(f"\n=== 时间格式化 ===")
durations = [30, 90, 150, 3600, 3665, 7200]
for duration in durations:
formatted = formatter.format_duration(duration)
print(f"{duration:>6} 秒 = {formatted}")
# 进度条格式化
print(f"\n=== 进度条格式化 ===")
for i in range(0, 101, 20):
progress = formatter.format_progress_bar(i, 100)
print(progress)
# 货币格式化
print(f"\n=== 货币格式化 ===")
amounts = [1234.56, 1000000, 0.99, 12345678.90]
for amount in amounts:
formatted = formatter.format_money(amount)
print(f"{amount:>12} = {formatted}")
字符编码和Unicode
字符编码基础
print("=== 字符编码基础 ===")
# Unicode字符串
unicode_text = "Hello 世界 🌍 🐍"
print(f"Unicode文本: {unicode_text}")
print(f"字符串长度: {len(unicode_text)}")
print(f"字符串类型: {type(unicode_text)}")
# 字符编码
print(f"\n=== 字符编码 ===")
text = "Python编程"
print(f"原始文本: {text}")
# 编码为字节
utf8_bytes = text.encode('utf-8')
gbk_bytes = text.encode('gbk')
print(f"UTF-8编码: {utf8_bytes}")
print(f"GBK编码: {gbk_bytes}")
print(f"UTF-8长度: {len(utf8_bytes)} 字节")
print(f"GBK长度: {len(gbk_bytes)} 字节")
# 解码为字符串
decoded_utf8 = utf8_bytes.decode('utf-8')
decoded_gbk = gbk_bytes.decode('gbk')
print(f"UTF-8解码: {decoded_utf8}")
print(f"GBK解码: {decoded_gbk}")
# 编码错误处理
print(f"\n=== 编码错误处理 ===")
problematic_text = "Hello 世界 🌍"
# 不同的错误处理策略
error_strategies = ['ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace']
for strategy in error_strategies:
try:
# 尝试用ASCII编码(会失败)
encoded = problematic_text.encode('ascii', errors=strategy)
print(f"{strategy:>18}: {encoded}")
except UnicodeEncodeError as e:
print(f"{strategy:>18}: 编码失败 - {e}")
# 解码错误处理
print(f"\n=== 解码错误处理 ===")
bad_bytes = b'\xff\xfe\x00\x00' # 无效的UTF-8字节序列
for strategy in error_strategies:
try:
decoded = bad_bytes.decode('utf-8', errors=strategy)
print(f"{strategy:>18}: {repr(decoded)}")
except UnicodeDecodeError as e:
print(f"{strategy:>18}: 解码失败 - {e}")
Unicode字符处理
import unicodedata
print("=== Unicode字符处理 ===")
# Unicode字符信息
characters = ['A', '中', '🐍', 'é', 'ñ']
print(f"{'字符':<5} {'Unicode':<10} {'名称':<30} {'类别':<5} {'数值':<5}")
print("-" * 65)
for char in characters:
unicode_point = ord(char)
name = unicodedata.name(char, '未知')
category = unicodedata.category(char)
numeric = unicodedata.numeric(char, None)
print(f"{char:<5} U+{unicode_point:04X} {name:<30} {category:<5} {numeric or 'N/A':<5}")
# Unicode规范化
print(f"\n=== Unicode规范化 ===")
# 组合字符示例
text1 = "café" # é 是单个字符
text2 = "cafe\u0301" # e + 组合重音符
print(f"文本1: {text1} (长度: {len(text1)})")
print(f"文本2: {text2} (长度: {len(text2)})")
print(f"相等性: {text1 == text2}")
# 规范化形式
normalization_forms = ['NFC', 'NFD', 'NFKC', 'NFKD']
for form in normalization_forms:
norm1 = unicodedata.normalize(form, text1)
norm2 = unicodedata.normalize(form, text2)
print(f"{form}: '{norm1}' (长度: {len(norm1)}) == '{norm2}' (长度: {len(norm2)}) -> {norm1 == norm2}")
# 字符分类
print(f"\n=== 字符分类 ===")
test_chars = 'Aa1中🐍 \t\n'
print(f"测试字符: {repr(test_chars)}")
for char in test_chars:
if char.isalpha():
char_type = "字母"
elif char.isdigit():
char_type = "数字"
elif char.isspace():
char_type = "空白"
elif char.isprintable():
char_type = "可打印"
else:
char_type = "其他"
category = unicodedata.category(char)
print(f"'{char}' -> {char_type} (Unicode类别: {category})")
文本处理实用工具
class UnicodeTextProcessor:
"""Unicode文本处理器"""
@staticmethod
def remove_accents(text):
"""移除重音符号"""
# 分解字符,然后过滤掉组合字符
nfd = unicodedata.normalize('NFD', text)
return ''.join(char for char in nfd if unicodedata.category(char) != 'Mn')
@staticmethod
def is_chinese(char):
"""判断是否为中文字符"""
return '\u4e00' <= char <= '\u9fff'
@staticmethod
def count_character_types(text):
"""统计字符类型"""
counts = {
'chinese': 0,
'english': 0,
'digits': 0,
'punctuation': 0,
'whitespace': 0,
'other': 0
}
for char in text:
if UnicodeTextProcessor.is_chinese(char):
counts['chinese'] += 1
elif char.isalpha() and ord(char) < 128: # ASCII字母
counts['english'] += 1
elif char.isdigit():
counts['digits'] += 1
elif char in '.,!?;:"\'-()[]{}': # 常见标点
counts['punctuation'] += 1
elif char.isspace():
counts['whitespace'] += 1
else:
counts['other'] += 1
return counts
@staticmethod
def clean_text(text):
"""清理文本"""
# 规范化Unicode
text = unicodedata.normalize('NFKC', text)
# 移除控制字符
cleaned = ''.join(char for char in text if unicodedata.category(char)[0] != 'C' or char in '\t\n\r')
# 规范化空白
import re
cleaned = re.sub(r'\s+', ' ', cleaned)
return cleaned.strip()
@staticmethod
def detect_encoding(byte_data):
"""检测字节数据的编码"""
encodings = ['utf-8', 'gbk', 'gb2312', 'big5', 'latin1']
for encoding in encodings:
try:
decoded = byte_data.decode(encoding)
return encoding, decoded
except UnicodeDecodeError:
continue
return None, None
# 测试Unicode文本处理器
processor = UnicodeTextProcessor()
print("=== Unicode文本处理器测试 ===")
# 移除重音符号
accented_text = "café, naïve, résumé, piñata"
print(f"原文本: {accented_text}")
no_accents = processor.remove_accents(accented_text)
print(f"移除重音: {no_accents}")
# 字符类型统计
mixed_text = "Hello 世界! 123 Python编程 🐍"
print(f"\n混合文本: {mixed_text}")
char_counts = processor.count_character_types(mixed_text)
print("字符统计:")
for char_type, count in char_counts.items():
if count > 0:
print(f" {char_type}: {count}")
# 文本清理
dirty_text = " Hello\t\t世界\n\n \r Python \u200b编程 "
print(f"\n脏文本: {repr(dirty_text)}")
cleaned = processor.clean_text(dirty_text)
print(f"清理后: {repr(cleaned)}")
# 编码检测
test_bytes = "Hello 世界".encode('utf-8')
detected_encoding, decoded_text = processor.detect_encoding(test_bytes)
print(f"\n字节数据: {test_bytes}")
print(f"检测编码: {detected_encoding}")
print(f"解码文本: {decoded_text}")
正则表达式与字符串
正则表达式基础
import re
print("=== 正则表达式基础 ===")
# 基本匹配
text = "Python是一种编程语言,Python很强大"
pattern = r"Python"
# 查找方法
print(f"文本: {text}")
print(f"模式: {pattern}")
print(f"\nsearch(): {re.search(pattern, text)}")
print(f"match(): {re.match(pattern, text)}")
print(f"findall(): {re.findall(pattern, text)}")
print(f"finditer(): {list(re.finditer(pattern, text))}")
# 匹配对象
match = re.search(pattern, text)
if match:
print(f"\n匹配对象信息:")
print(f"匹配内容: {match.group()}")
print(f"开始位置: {match.start()}")
print(f"结束位置: {match.end()}")
print(f"位置范围: {match.span()}")
# 编译正则表达式
compiled_pattern = re.compile(pattern)
print(f"\n编译后的模式: {compiled_pattern}")
print(f"编译后查找: {compiled_pattern.findall(text)}")
# 常用正则模式
print(f"\n=== 常用正则模式 ===")
patterns = {
r"\d+": "数字",
r"\w+": "单词字符",
r"\s+": "空白字符",
r"[a-zA-Z]+": "英文字母",
r"[\u4e00-\u9fff]+": "中文字符",
r"\b\w+\b": "完整单词",
r"^\w+": "行首单词",
r"\w+$": "行尾单词"
}
test_text = "Hello 世界123 Python编程!"
print(f"测试文本: {test_text}")
for pattern, description in patterns.items():
matches = re.findall(pattern, test_text)
print(f"{pattern:<20} ({description}): {matches}")
高级正则表达式
print("=== 高级正则表达式 ===")
# 分组捕获
email_pattern = r"([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
email_text = "联系邮箱: john.doe@example.com 或 admin@test.org"
print(f"邮箱文本: {email_text}")
print(f"邮箱模式: {email_pattern}")
# 查找所有邮箱
emails = re.findall(email_pattern, email_text)
print(f"找到的邮箱: {emails}")
# 详细匹配信息
for match in re.finditer(email_pattern, email_text):
print(f"完整邮箱: {match.group(0)}")
print(f"用户名: {match.group(1)}")
print(f"域名: {match.group(2)}")
print(f"位置: {match.span()}")
print()
# 命名分组
named_pattern = r"(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
for match in re.finditer(named_pattern, email_text):
print(f"命名分组 - 用户名: {match.group('username')}, 域名: {match.group('domain')}")
# 非捕获分组
non_capture_pattern = r"(?:https?://)?(www\.)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
url_text = "访问 https://www.example.com 或 http://test.org"
print(f"\nURL文本: {url_text}")
domains = re.findall(non_capture_pattern, url_text)
print(f"域名: {domains}")
# 前瞻和后顾断言
password_pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$"
passwords = ["password", "Password1", "Password1!", "Pass1!", "StrongPass123!"]
print(f"\n密码强度检查:")
for pwd in passwords:
is_strong = bool(re.match(password_pattern, pwd))
print(f"{pwd:<15}: {'强' if is_strong else '弱'}")
# 贪婪与非贪婪匹配
html_text = "<div>内容1</div><div>内容2</div>"
greedy_pattern = r"<div>.*</div>"
non_greedy_pattern = r"<div>.*?</div>"
print(f"\nHTML文本: {html_text}")
print(f"贪婪匹配: {re.findall(greedy_pattern, html_text)}")
print(f"非贪婪匹配: {re.findall(non_greedy_pattern, html_text)}")
正则表达式实用工具
class RegexToolkit:
"""正则表达式工具包"""
# 常用正则模式
PATTERNS = {
'email': r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
'phone_cn': r'^1[3-9]\d{9}$',
'id_card_cn': r'^\d{17}[\dXx]$',
'url': r'^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:/[^\s]*)?$',
'ip_address': r'^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$',
'date_iso': r'^\d{4}-\d{2}-\d{2}$',
'time_24h': r'^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$',
'chinese': r'[\u4e00-\u9fff]+',
'english': r'[a-zA-Z]+',
'number': r'-?\d+(?:\.\d+)?'
}
@classmethod
def validate(cls, text, pattern_name):
"""验证文本是否匹配指定模式"""
if pattern_name not in cls.PATTERNS:
raise ValueError(f"未知模式: {pattern_name}")
pattern = cls.PATTERNS[pattern_name]
return bool(re.match(pattern, text))
@classmethod
def extract(cls, text, pattern_name):
"""从文本中提取匹配指定模式的内容"""
if pattern_name not in cls.PATTERNS:
raise ValueError(f"未知模式: {pattern_name}")
pattern = cls.PATTERNS[pattern_name]
return re.findall(pattern, text)
@staticmethod
def clean_whitespace(text):
"""清理多余的空白字符"""
# 将多个空白字符替换为单个空格
text = re.sub(r'\s+', ' ', text)
# 移除行首行尾空白
return text.strip()
@staticmethod
def extract_numbers(text):
"""提取文本中的所有数字"""
pattern = r'-?\d+(?:\.\d+)?'
numbers = re.findall(pattern, text)
return [float(num) if '.' in num else int(num) for num in numbers]
@staticmethod
def mask_sensitive_info(text):
"""遮蔽敏感信息"""
# 遮蔽手机号
text = re.sub(r'(1[3-9]\d)(\d{4})(\d{4})', r'\1****\3', text)
# 遮蔽身份证号
text = re.sub(r'(\d{6})(\d{8})(\d{4})', r'\1********\3', text)
# 遮蔽邮箱
text = re.sub(r'([a-zA-Z0-9._%+-]{1,3})[a-zA-Z0-9._%+-]*@', r'\1***@', text)
return text
@staticmethod
def split_sentences(text):
"""智能分句"""
# 中英文句子分割
pattern = r'[.!?。!?]+'
sentences = re.split(pattern, text)
return [s.strip() for s in sentences if s.strip()]
@staticmethod
def highlight_keywords(text, keywords, tag='<mark>'):
"""高亮关键词"""
if isinstance(keywords, str):
keywords = [keywords]
for keyword in keywords:
pattern = re.escape(keyword)
replacement = f'{tag}{keyword}</{tag.strip("<>")}>' if tag.startswith('<') else f'{tag}{keyword}{tag}'
text = re.sub(pattern, replacement, text, flags=re.IGNORECASE)
return text
# 测试正则表达式工具包
toolkit = RegexToolkit()
print("=== 正则表达式工具包测试 ===")
# 验证测试
test_data = {
'email': ['test@example.com', 'invalid-email', 'user@domain.co.uk'],
'phone_cn': ['13812345678', '12345678901', '18888888888'],
'id_card_cn': ['110101199001011234', '12345', '110101199001011235'],
'url': ['https://www.example.com', 'http://test.org/path', 'invalid-url']
}
for pattern_name, test_values in test_data.items():
print(f"\n{pattern_name} 验证:")
for value in test_values:
is_valid = toolkit.validate(value, pattern_name)
print(f" {value:<25}: {'✓' if is_valid else '✗'}")
# 提取测试
text_with_data = "联系方式: 13812345678, 邮箱: john@example.com, 网站: https://www.test.com"
print(f"\n提取测试:")
print(f"原文本: {text_with_data}")
print(f"手机号: {toolkit.extract(text_with_data, 'phone_cn')}")
print(f"邮箱: {toolkit.extract(text_with_data, 'email')}")
print(f"URL: {toolkit.extract(text_with_data, 'url')}")
# 数字提取
number_text = "价格: 99.99元, 数量: -5个, 总计: 1234.56元"
print(f"\n数字提取:")
print(f"原文本: {number_text}")
numbers = toolkit.extract_numbers(number_text)
print(f"提取的数字: {numbers}")
# 敏感信息遮蔽
sensitive_text = "手机: 13812345678, 身份证: 110101199001011234, 邮箱: john.doe@example.com"
print(f"\n敏感信息遮蔽:")
print(f"原文本: {sensitive_text}")
masked = toolkit.mask_sensitive_info(sensitive_text)
print(f"遮蔽后: {masked}")
# 关键词高亮
keyword_text = "Python是一种强大的编程语言,Python在数据科学领域很受欢迎"
print(f"\n关键词高亮:")
print(f"原文本: {keyword_text}")
highlighted = toolkit.highlight_keywords(keyword_text, ['Python', '编程'], '<strong>')
print(f"高亮后: {highlighted}")
字符串性能优化
字符串连接性能
import time
import sys
print("=== 字符串连接性能测试 ===")
def time_function(func, *args, **kwargs):
"""测量函数执行时间"""
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
return result, end_time - start_time
# 不同的字符串连接方法
def concat_with_plus(strings):
"""使用 + 连接"""
result = ""
for s in strings:
result += s
return result
def concat_with_join(strings):
"""使用 join 连接"""
return "".join(strings)
def concat_with_format(strings):
"""使用 format 连接"""
return "{}".format("".join(strings))
def concat_with_fstring(strings):
"""使用 f-string 连接"""
return f"{"".join(strings)}"
def concat_with_list(strings):
"""使用列表收集再连接"""
result_list = []
for s in strings:
result_list.append(s)
return "".join(result_list)
# 测试数据
test_strings = ["Hello", " ", "World", " ", "Python", " ", "Programming"] * 1000
print(f"测试数据长度: {len(test_strings)}")
print(f"预期结果长度: {len(''.join(test_strings))}")
# 性能测试
methods = [
("+ 连接", concat_with_plus),
("join 连接", concat_with_join),
("format 连接", concat_with_format),
("f-string 连接", concat_with_fstring),
("列表收集", concat_with_list)
]
print(f"\n{'方法':<15} {'时间(秒)':<12} {'内存使用':<12} {'结果长度':<10}")
print("-" * 55)
for method_name, method_func in methods:
# 测量内存使用(简单估算)
initial_size = sys.getsizeof("")
result, execution_time = time_function(method_func, test_strings)
final_size = sys.getsizeof(result)
memory_used = final_size - initial_size
print(f"{method_name:<15} {execution_time:<12.6f} {memory_used:<12} {len(result):<10}")
字符串查找优化
print("=== 字符串查找优化 ===")
# 创建大文本用于测试
large_text = "Python编程" * 10000 + "目标字符串" + "更多内容" * 5000
search_target = "目标字符串"
print(f"大文本长度: {len(large_text):,} 字符")
print(f"查找目标: {search_target}")
# 不同查找方法
def find_with_in(text, target):
"""使用 in 操作符"""
return target in text
def find_with_find(text, target):
"""使用 find 方法"""
return text.find(target) != -1
def find_with_index(text, target):
"""使用 index 方法(带异常处理)"""
try:
text.index(target)
return True
except ValueError:
return False
def find_with_regex(text, target):
"""使用正则表达式"""
import re
return bool(re.search(re.escape(target), text))
def find_with_count(text, target):
"""使用 count 方法"""
return text.count(target) > 0
# 查找性能测试
find_methods = [
("in 操作符", find_with_in),
("find 方法", find_with_find),
("index 方法", find_with_index),
("正则表达式", find_with_regex),
("count 方法", find_with_count)
]
print(f"\n{'查找方法':<15} {'时间(秒)':<12} {'结果':<8}")
print("-" * 40)
for method_name, method_func in find_methods:
result, execution_time = time_function(method_func, large_text, search_target)
print(f"{method_name:<15} {execution_time:<12.6f} {result:<8}")
内存优化技巧
class StringMemoryOptimizer:
"""字符串内存优化工具"""
@staticmethod
def use_slots_for_strings():
"""使用 __slots__ 优化字符串存储"""
class OptimizedStringContainer:
__slots__ = ['value', 'length', 'hash_value']
def __init__(self, value):
self.value = value
self.length = len(value)
self.hash_value = hash(value)
def __str__(self):
return self.value
def __len__(self):
return self.length
def __hash__(self):
return self.hash_value
return OptimizedStringContainer
@staticmethod
def lazy_string_evaluation():
"""延迟字符串求值"""
class LazyString:
def __init__(self, func, *args, **kwargs):
self._func = func
self._args = args
self._kwargs = kwargs
self._value = None
self._evaluated = False
def __str__(self):
if not self._evaluated:
self._value = self._func(*self._args, **self._kwargs)
self._evaluated = True
return self._value
def __len__(self):
return len(str(self))
return LazyString
@staticmethod
def string_interning_demo():
"""字符串驻留演示"""
import sys
# 手动驻留字符串
str1 = "hello_world_" + "123"
str2 = "hello_world_" + "123"
print(f"驻留前: str1 is str2 = {str1 is str2}")
# 手动驻留
str1_interned = sys.intern(str1)
str2_interned = sys.intern(str2)
print(f"驻留后: str1_interned is str2_interned = {str1_interned is str2_interned}")
return str1_interned, str2_interned
@staticmethod
def memory_efficient_processing(large_text):
"""内存高效的文本处理"""
# 使用生成器避免创建大量中间字符串
def process_lines(text):
for line in text.splitlines():
if line.strip(): # 只处理非空行
yield line.strip().lower()
# 使用迭代器而不是列表
processed_lines = process_lines(large_text)
# 逐行处理,避免一次性加载所有数据到内存
word_count = {}
for line in processed_lines:
for word in line.split():
word_count[word] = word_count.get(word, 0) + 1
return word_count
# 测试内存优化
optimizer = StringMemoryOptimizer()
print("=== 字符串内存优化测试 ===")
# 测试 __slots__ 优化
OptimizedContainer = optimizer.use_slots_for_strings()
regular_string = "Hello World"
optimized_container = OptimizedContainer(regular_string)
print(f"普通字符串大小: {sys.getsizeof(regular_string)} 字节")
print(f"优化容器大小: {sys.getsizeof(optimized_container)} 字节")
print(f"容器内容: {optimized_container}")
print(f"容器长度: {len(optimized_container)}")
# 测试延迟求值
LazyString = optimizer.lazy_string_evaluation()
def expensive_string_operation():
"""模拟昂贵的字符串操作"""
print("执行昂贵的字符串操作...")
return "计算结果: " + str(sum(range(1000)))
lazy_str = LazyString(expensive_string_operation)
print(f"\n创建延迟字符串(未求值)")
print(f"首次访问: {lazy_str}") # 这时才执行计算
print(f"再次访问: {lazy_str}") # 使用缓存结果
# 测试字符串驻留
print(f"\n=== 字符串驻留测试 ===")
interned_strings = optimizer.string_interning_demo()
# 测试内存高效处理
test_text = """第一行内容
第二行内容
第四行内容
第五行内容"""
print(f"\n=== 内存高效处理测试 ===")
word_count = optimizer.memory_efficient_processing(test_text)
print(f"词频统计: {word_count}")
实践练习
练习1:文本分析器
class TextAnalyzer:
"""文本分析器"""
def __init__(self, text):
self.text = text
self.words = self._extract_words()
self.sentences = self._extract_sentences()
def _extract_words(self):
"""提取单词"""
import re
# 提取中英文单词
pattern = r'[\w\u4e00-\u9fff]+'
return re.findall(pattern, self.text.lower())
def _extract_sentences(self):
"""提取句子"""
import re
pattern = r'[.!?。!?]+'
sentences = re.split(pattern, self.text)
return [s.strip() for s in sentences if s.strip()]
def word_frequency(self):
"""词频统计"""
freq = {}
for word in self.words:
freq[word] = freq.get(word, 0) + 1
return dict(sorted(freq.items(), key=lambda x: x[1], reverse=True))
def character_count(self):
"""字符统计"""
return {
'total': len(self.text),
'letters': sum(1 for c in self.text if c.isalpha()),
'digits': sum(1 for c in self.text if c.isdigit()),
'spaces': sum(1 for c in self.text if c.isspace()),
'punctuation': sum(1 for c in self.text if not c.isalnum() and not c.isspace())
}
def readability_score(self):
"""可读性评分(简化版)"""
if not self.sentences:
return 0
avg_words_per_sentence = len(self.words) / len(self.sentences)
avg_chars_per_word = sum(len(word) for word in self.words) / len(self.words) if self.words else 0
# 简化的可读性评分
score = 100 - (avg_words_per_sentence * 1.5) - (avg_chars_per_word * 2)
return max(0, min(100, score))
def generate_summary(self, max_sentences=3):
"""生成摘要"""
if len(self.sentences) <= max_sentences:
return '. '.join(self.sentences) + '.'
# 简单的摘要算法:选择包含高频词的句子
word_freq = self.word_frequency()
top_words = set(list(word_freq.keys())[:10]) # 前10个高频词
sentence_scores = []
for sentence in self.sentences:
score = sum(1 for word in sentence.lower().split() if word in top_words)
sentence_scores.append((score, sentence))
# 选择得分最高的句子
sentence_scores.sort(reverse=True)
summary_sentences = [sent for _, sent in sentence_scores[:max_sentences]]
return '. '.join(summary_sentences) + '.'
# 测试文本分析器
test_text = """
Python是一种高级编程语言。Python具有简洁的语法和强大的功能。
许多开发者选择Python进行数据分析和机器学习。
Python的生态系统非常丰富,有大量的第三方库可以使用。
学习Python可以帮助你快速开发各种应用程序。
"""
analyzer = TextAnalyzer(test_text)
print("=== 文本分析结果 ===")
print(f"原文本:\n{test_text}")
print(f"\n词频统计(前10):")
word_freq = analyzer.word_frequency()
for word, freq in list(word_freq.items())[:10]:
print(f" {word}: {freq}")
print(f"\n字符统计:")
char_count = analyzer.character_count()
for char_type, count in char_count.items():
print(f" {char_type}: {count}")
print(f"\n可读性评分: {analyzer.readability_score():.1f}")
print(f"\n摘要:\n{analyzer.generate_summary()}")
练习2:字符串格式化工具
class StringFormatter:
"""字符串格式化工具"""
@staticmethod
def format_table(data, headers=None, align='left', border=True):
"""格式化表格"""
if not data:
return ""
# 准备数据
if headers:
all_rows = [headers] + data
else:
all_rows = data
# 计算列宽
col_widths = []
for col in range(len(all_rows[0])):
max_width = max(len(str(row[col])) for row in all_rows)
col_widths.append(max_width + 2) # 添加padding
# 格式化函数
def format_row(row, is_header=False):
formatted_cells = []
for i, (cell, width) in enumerate(zip(row, col_widths)):
cell_str = str(cell)
if align == 'left':
formatted = f" {cell_str:<{width-2}} "
elif align == 'right':
formatted = f" {cell_str:>{width-2}} "
else: # center
formatted = f" {cell_str:^{width-2}} "
formatted_cells.append(formatted)
if border:
return '|' + '|'.join(formatted_cells) + '|'
else:
return ' '.join(formatted_cells)
# 生成表格
lines = []
if border:
# 顶部边框
border_line = '+' + '+'.join('-' * width for width in col_widths) + '+'
lines.append(border_line)
# 表头
if headers:
lines.append(format_row(headers, True))
if border:
lines.append(border_line)
# 数据行
for row in data:
lines.append(format_row(row))
if border:
# 底部边框
lines.append(border_line)
return '\n'.join(lines)
@staticmethod
def format_json_like(data, indent=2):
"""类JSON格式化"""
def format_value(value, current_indent=0):
spaces = ' ' * current_indent
if isinstance(value, dict):
if not value:
return '{}'
lines = ['{']
items = list(value.items())
for i, (k, v) in enumerate(items):
comma = ',' if i < len(items) - 1 else ''
formatted_value = format_value(v, current_indent + indent)
lines.append(f'{spaces}{" " * indent}"{k}": {formatted_value}{comma}')
lines.append(f'{spaces}}}')
return '\n'.join(lines)
elif isinstance(value, list):
if not value:
return '[]'
lines = ['[']
for i, item in enumerate(value):
comma = ',' if i < len(value) - 1 else ''
formatted_item = format_value(item, current_indent + indent)
lines.append(f'{spaces}{" " * indent}{formatted_item}{comma}')
lines.append(f'{spaces}]')
return '\n'.join(lines)
elif isinstance(value, str):
return f'"{value}"'
else:
return str(value)
return format_value(data)
@staticmethod
def format_code_block(code, language='python', line_numbers=True):
"""格式化代码块"""
lines = code.strip().split('\n')
if line_numbers:
max_line_num = len(lines)
line_num_width = len(str(max_line_num))
formatted_lines = []
for i, line in enumerate(lines, 1):
line_num = f"{i:>{line_num_width}}"
formatted_lines.append(f"{line_num} | {line}")
code_content = '\n'.join(formatted_lines)
else:
code_content = '\n'.join(lines)
return f"```{language}\n{code_content}\n```"
# 测试字符串格式化工具
formatter = StringFormatter()
print("=== 字符串格式化工具测试 ===")
# 表格格式化测试
print("=== 表格格式化 ===")
headers = ['姓名', '年龄', '城市', '职业']
data = [
['张三', 25, '北京', '工程师'],
['李四', 30, '上海', '设计师'],
['王五', 28, '广州', '产品经理']
]
table = formatter.format_table(data, headers, align='center')
print(table)
# JSON格式化测试
print("\n=== JSON格式化 ===")
test_data = {
'name': '张三',
'age': 25,
'skills': ['Python', 'JavaScript', 'SQL'],
'address': {
'city': '北京',
'district': '朝阳区'
}
}
formatted_json = formatter.format_json_like(test_data)
print(formatted_json)
# 代码块格式化测试
print("\n=== 代码块格式化 ===")
code = '''def hello_world():
print("Hello, World!")
return "success"
result = hello_world()'''
formatted_code = formatter.format_code_block(code, 'python', True)
print(formatted_code)
练习3:文本处理管道
class TextProcessingPipeline:
"""文本处理管道"""
def __init__(self):
self.processors = []
def add_processor(self, processor):
"""添加处理器"""
self.processors.append(processor)
return self
def process(self, text):
"""执行处理管道"""
result = text
for processor in self.processors:
result = processor(result)
return result
@staticmethod
def remove_extra_whitespace(text):
"""移除多余空白"""
import re
return re.sub(r'\s+', ' ', text).strip()
@staticmethod
def normalize_punctuation(text):
"""标准化标点符号"""
replacements = {
',': ',',
'。': '.',
'!': '!',
'?': '?',
':': ':',
';': ';'
}
for old, new in replacements.items():
text = text.replace(old, new)
return text
@staticmethod
def remove_urls(text):
"""移除URL"""
import re
url_pattern = r'https?://[^\s]+'
return re.sub(url_pattern, '', text)
@staticmethod
def remove_emails(text):
"""移除邮箱地址"""
import re
email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
return re.sub(email_pattern, '', text)
@staticmethod
def extract_hashtags(text):
"""提取话题标签"""
import re
hashtag_pattern = r'#[\w\u4e00-\u9fff]+'
return re.findall(hashtag_pattern, text)
@staticmethod
def censor_profanity(text, profanity_list=None):
"""屏蔽敏感词"""
if profanity_list is None:
profanity_list = ['敏感词1', '敏感词2'] # 示例敏感词
for word in profanity_list:
if word in text:
text = text.replace(word, '*' * len(word))
return text
# 测试文本处理管道
pipeline = TextProcessingPipeline()
# 配置处理管道
pipeline.add_processor(TextProcessingPipeline.remove_urls)
pipeline.add_processor(TextProcessingPipeline.remove_emails)
pipeline.add_processor(TextProcessingPipeline.normalize_punctuation)
pipeline.add_processor(TextProcessingPipeline.remove_extra_whitespace)
pipeline.add_processor(TextProcessingPipeline.censor_profanity)
# 测试文本
test_text = """
这是一个测试文本,包含URL: https://www.example.com 和邮箱: test@example.com。
还有一些 多余的 空白字符。
包含中文标点符号,如:逗号,句号。感叹号!问号?
#Python #编程 #学习
可能包含敏感词1的内容。
"""
print("=== 文本处理管道测试 ===")
print(f"原始文本:\n{test_text}")
print(f"\n处理后文本:\n{pipeline.process(test_text)}")
# 提取话题标签
hashtags = TextProcessingPipeline.extract_hashtags(test_text)
print(f"\n提取的话题标签: {hashtags}")
总结
核心知识点
-
字符串基础
- 字符串的不可变性和内存优化
- 多种创建方式:单引号、双引号、三引号、原始字符串、f-string
- 字符串驻留机制
-
索引和切片
- 正负索引访问
- 切片操作的灵活性
- 边界安全性
-
字符串方法
- 查找和检查:
find(),index(),count(),startswith(),endswith() - 验证方法:
isdigit(),isalpha(),isalnum()等 - 转换方法:大小写转换、去除空白、填充对齐
- 分割和连接:
split(),join(),partition()
- 查找和检查:
-
字符串格式化
- 传统方法:
%格式化、format()方法 - 现代方法:f-string(推荐)
- 格式化规范和高级技巧
- 传统方法:
-
字符编码
- Unicode和字符编码基础
- 编码解码操作
- 错误处理策略
-
正则表达式
- 基本模式匹配
- 高级特性:分组、断言、贪婪匹配
- 实用工具类的设计
-
性能优化
- 字符串连接的最佳实践
- 内存使用优化
- 查找操作的性能对比
技能掌握
完成本章学习后,你应该能够:
- ✅ 熟练使用各种字符串操作方法
- ✅ 选择合适的字符串格式化方式
- ✅ 处理字符编码问题
- ✅ 编写高效的字符串处理代码
- ✅ 使用正则表达式解决复杂文本问题
- ✅ 设计文本处理工具和管道
最佳实践
-
性能考虑
- 大量字符串连接使用
join()而不是+ - 使用 f-string 进行格式化
- 避免不必要的字符串复制
- 大量字符串连接使用
-
代码可读性
- 使用描述性的变量名
- 适当使用原始字符串处理路径和正则表达式
- 添加必要的注释说明复杂的字符串操作
-
错误处理
- 处理字符编码错误
- 验证输入数据的格式
- 使用异常处理保护索引访问
-
国际化支持
- 正确处理Unicode字符
- 考虑不同语言的文本特性
- 使用适当的字符编码
常见陷阱
-
字符串不可变性误解
# 错误:认为字符串可以修改 # text[0] = 'H' # TypeError # 正确:创建新字符串 text = 'h' + text[1:] -
编码问题
# 注意编码一致性 text = "中文" bytes_data = text.encode('utf-8') decoded = bytes_data.decode('utf-8') # 使用相同编码 -
性能陷阱
# 低效的字符串连接 result = "" for item in items: result += str(item) # 每次都创建新字符串 # 高效的方式 result = "".join(str(item) for item in items)
下一步学习
掌握了字符串处理后,建议继续学习:
- 006-列表与元组操作 - 学习序列数据结构
- 007-字典与集合应用 - 掌握映射和集合类型
- 文件操作和I/O处理
- 数据序列化和反序列化
扩展阅读
📝 更新记录
- 2024-01-XX: 创建文档,包含字符串处理的完整内容
- 版本: v1.0.0
- 作者: Python教程团队

2万+

被折叠的 条评论
为什么被折叠?



