005-字符串处理详解

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}")

总结

核心知识点

  1. 字符串基础

    • 字符串的不可变性和内存优化
    • 多种创建方式:单引号、双引号、三引号、原始字符串、f-string
    • 字符串驻留机制
  2. 索引和切片

    • 正负索引访问
    • 切片操作的灵活性
    • 边界安全性
  3. 字符串方法

    • 查找和检查:find(), index(), count(), startswith(), endswith()
    • 验证方法:isdigit(), isalpha(), isalnum()
    • 转换方法:大小写转换、去除空白、填充对齐
    • 分割和连接:split(), join(), partition()
  4. 字符串格式化

    • 传统方法:% 格式化、format() 方法
    • 现代方法:f-string(推荐)
    • 格式化规范和高级技巧
  5. 字符编码

    • Unicode和字符编码基础
    • 编码解码操作
    • 错误处理策略
  6. 正则表达式

    • 基本模式匹配
    • 高级特性:分组、断言、贪婪匹配
    • 实用工具类的设计
  7. 性能优化

    • 字符串连接的最佳实践
    • 内存使用优化
    • 查找操作的性能对比

技能掌握

完成本章学习后,你应该能够:

  • ✅ 熟练使用各种字符串操作方法
  • ✅ 选择合适的字符串格式化方式
  • ✅ 处理字符编码问题
  • ✅ 编写高效的字符串处理代码
  • ✅ 使用正则表达式解决复杂文本问题
  • ✅ 设计文本处理工具和管道

最佳实践

  1. 性能考虑

    • 大量字符串连接使用 join() 而不是 +
    • 使用 f-string 进行格式化
    • 避免不必要的字符串复制
  2. 代码可读性

    • 使用描述性的变量名
    • 适当使用原始字符串处理路径和正则表达式
    • 添加必要的注释说明复杂的字符串操作
  3. 错误处理

    • 处理字符编码错误
    • 验证输入数据的格式
    • 使用异常处理保护索引访问
  4. 国际化支持

    • 正确处理Unicode字符
    • 考虑不同语言的文本特性
    • 使用适当的字符编码

常见陷阱

  1. 字符串不可变性误解

    # 错误:认为字符串可以修改
    # text[0] = 'H'  # TypeError
    
    # 正确:创建新字符串
    text = 'h' + text[1:]
    
  2. 编码问题

    # 注意编码一致性
    text = "中文"
    bytes_data = text.encode('utf-8')
    decoded = bytes_data.decode('utf-8')  # 使用相同编码
    
  3. 性能陷阱

    # 低效的字符串连接
    result = ""
    for item in items:
        result += str(item)  # 每次都创建新字符串
    
    # 高效的方式
    result = "".join(str(item) for item in items)
    

下一步学习

掌握了字符串处理后,建议继续学习:

扩展阅读


📝 更新记录

  • 2024-01-XX: 创建文档,包含字符串处理的完整内容
  • 版本: v1.0.0
  • 作者: Python教程团队
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lvjesus

码力充电

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值