[Python] Python知识学习08

449 0
Honkers 2026-4-30 13:45:45 来自手机 | 显示全部楼层 |阅读模式

第一部分:Python 文件IO基础

1 文件 IO 概念

1.1 基本定义

  • 文件 IO:即文件 Input/Output,实现程序与操作系统之间的文件数据交互。

  • 输入流(Input):将文件中的数据读取到内存(程序)中。

  • 输出流(Output):将内存(程序)中的数据写入到文件中。

  • 核心函数:Python 内置 open() 函数,用于打开文件并返回数据流(输入流 / 输出流),操作失败会抛出 OSError 异常。

1.2 文件分类(操作系统层面)

文件类型底层组成校验方式典型示例
字符文件字符(文本)记事本打开无乱码源代码文件(.py)、配置文件(.txt)、文档(.md)
字节文件字节 / 二进制记事本打开会乱码图片(.jpg/.png)、音频(.mp3)、视频(.mp4)、压缩包(.zip)

1.3 open () 函数

1.3.1 语法

  1. open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
复制代码

1.3.2 参数说明

参数功能关键注意事项
file文件路径(相对路径 / 绝对路径)Windows 路径分隔符可用 \\ 或 /(避免转义问题)
mode操作模式(控制读写方式、文件类型)由 “操作符 + 类型符” 组合,默认 r(文本读)
encoding字符编码(仅字符文件需要)常用 UTF-8,字节文件无需指定
buffering缓冲策略默认 -1(系统自动缓冲),无需手动设置

1.3.3 mode 参数组合

模式组合功能描述适用文件类型
r / rt文本读(默认)字符文件
w / wt文本写(覆盖原有内容,文件不存在则创建)字符文件
a / at文本追加(在文件尾部写入,文件不存在则创建)字符文件
rb字节读字节文件
wb字节写(覆盖原有内容)字节文件
ab字节追加字节文件
r+ / rt+文本读写(可同时读和写)字符文件
rb+字节读写字节文件
x / xt / xb新建文件并写(文件已存在则报错)字符 / 字节文件

2 字符文件操作(文本文件)

字符文件操作需指定 encoding(如 UTF-8),避免中文乱码。核心流程:打开文件 → 读写数据 → 关闭文件

2.1 写入字符文件

2.1.1 基础语法(open () + close ())

  1. # 1. 准备文本数据
  2. content = "hello python!\n你好,Python 文件IO!"
  3. # 2. 打开文件:mode="wt"(文本写),指定编码 UTF-8
  4. file = open("test01.txt", mode="wt", encoding="UTF-8")
  5. # 3. 写入数据:write() 接收字符串
  6. file.write(content)
  7. # 4. 关闭文件(必须执行,释放资源)
  8. file.close()
复制代码

2.1.2 高级语法(with 语句,自动关闭)

with 语句会自动封装 “打开→操作→关闭” 流程,避免遗漏 close(),优先使用:

  1. # 自动打开文件,执行完代码块后自动关闭
  2. with open("test02.txt", mode="wt", encoding="UTF-8") as file:
  3. file.write("使用 with 语句写入文本数据")
复制代码

2.2 读取字符文件

2.2.1 基础读取(读取全部内容)

  1. # mode="rt" 可省略(默认 r),必须指定 encoding
  2. with open("test01.txt", encoding="UTF-8") as file:
  3. # read():读取文件全部内容,返回字符串
  4. data = file.read()
  5. print("读取结果:")
  6. print(data)
复制代码

2.2.2 进阶读取方法

方法功能示例
read(size)读取指定长度的字符(size 为字符数)file.read (10) → 读取前 10 个字符
readline()读取一行数据(以 \n 为分隔)逐行读取大文件时避免内存溢出
readlines()读取所有行,返回列表(每行作为一个元素)lines = file.readlines () → 列表推导式处理每行

2.2.3 逐行读取大文件(推荐)

  1. # 逐行读取,适合超大文本文件(避免一次性加载全部内容)
  2. with open("large_file.txt", encoding="UTF-8") as file:
  3. for line in file: # 直接迭代文件对象,逐行读取
  4. print(line.strip()) # strip() 去除换行符和空格
复制代码

2.3 字符文件操作注意事项

  • 写入后必须关闭文件(或用 with 语句),否则数据可能未真正写入(缓冲区未刷新)。

  • 读取时必须指定正确的 encoding,否则中文会乱码。

  • 若文件不存在,r 模式会报错,w/a/x 模式会自动创建文件。

3 字节文件操作(二进制文件)

字节文件操作模式需带 b(如 rb/wb),无需指定 encoding,数据以字节串(bytes 类型,前缀 b)处理。

3.1 读取字节文件(如图片、视频)

  1. # 读取图片文件(字节文件)
  2. with open("test.jpg", mode="rb") as file:
  3. # read() 返回字节串(bytes 类型)
  4. byte_data = file.read()
  5. print("字节数据长度:", len(byte_data))
  6. print("前10个字节:", byte_data[:10]) # 切片查看部分字节
复制代码

3.2 写入字节文件

字节数据需用 b'' 表示(或通过 str.encode(encoding) 转换):

  1. # 方式1:直接定义字节串
  2. byte_content1 = b"hello world!" # 英文直接加 b 前缀
  3. # 方式2:字符串编码为字节串(中文需指定编码)
  4. byte_content2 = "你好,字节文件!".encode("UTF-8")
  5. # 写入字节文件(mode="wb")
  6. with open("test03.bin", mode="wb") as file:
  7. file.write(byte_content1)
  8. file.write(b"\n") # 字节换行符
  9. file.write(byte_content2)
复制代码

3.3 字节与字符串转换

转换方向方法示例
字符串 → 字节str.encode(encoding)"中文".encode ("UTF-8") → 字节串
字节 → 字符串bytes.decode(encoding)b'\xe4\xb8\xad\xe6\x96\x87'.decode ("UTF-8") → 字符串

4 综合实战:文件复制(支持所有文件类型)

文件复制的核心是字节流操作(适配字符文件和字节文件),大文件需分块读取,避免内存溢出。

4.1 基础版:大文件分块复制

  1. import os
  2. def copy_file(source_path, target_path, chunk_size=1024*1024):
  3. """
  4. 大文件分块复制(支持所有文件类型)
  5. :param source_path: 源文件路径(必须是完整文件路径)
  6. :param target_path: 目标文件路径(必须包含文件名)
  7. :param chunk_size: 分块大小(默认 1MB,可调整)
  8. """
  9. # 检查源文件是否存在
  10. if not os.path.exists(source_path):
  11. raise FileNotFoundError(f"源文件不存在:{source_path}")
  12. # 确保目标文件所在目录存在
  13. target_dir = os.path.dirname(target_path)
  14. if not os.path.exists(target_dir):
  15. os.makedirs(target_dir)
  16. # 分块读写(字节模式)
  17. with open(source_path, "rb") as src_file, open(target_path, "wb") as tgt_file:
  18. while True:
  19. # 每次读取 chunk_size 字节
  20. chunk = src_file.read(chunk_size)
  21. if not chunk: # 读取到空字节串,说明文件结束
  22. break
  23. tgt_file.write(chunk) # 分块写入
  24. print(f"文件复制完成:{source_path} → {target_path}")
  25. # 调用函数:复制 ISO 镜像文件
  26. if __name__ == "__main__":
  27. source = "F:/BaiduNetdiskDownload/ubuntu-24.10-desktop-amd64.iso"
  28. target = "D:/bat/ubuntu_copy.iso"
  29. copy_file(source, target)
复制代码

4.2 进阶版:带进度提示的复制(tqdm 进度条)

需先安装:pip install tqdm

  1. from tqdm import tqdm
  2. import os
  3. def copy_file_with_progress(source_path, target_path, chunk_size=1024*1024):
  4. """带进度条的文件复制"""
  5. if not os.path.exists(source_path):
  6. raise FileNotFoundError(f"源文件不存在:{source_path}")
  7. # 获取源文件总大小(用于进度计算)
  8. total_size = os.path.getsize(source_path)
  9. target_dir = os.path.dirname(target_path)
  10. if not os.path.exists(target_dir):
  11. os.makedirs(target_dir)
  12. # 打开文件并创建进度条
  13. with open(source_path, "rb") as src_file, open(target_path, "wb") as tgt_file:
  14. # tqdm 进度条配置:总大小、单位、自动缩放
  15. with tqdm(
  16. total=total_size,
  17. unit="B",
  18. unit_scale=True,
  19. desc=f"复制 {os.path.basename(source_path)}"
  20. ) as progress_bar:
  21. while True:
  22. chunk = src_file.read(chunk_size)
  23. if not chunk:
  24. break
  25. tgt_file.write(chunk)
  26. # 更新进度条(每次更新读取的字节数)
  27. progress_bar.update(len(chunk))
  28. print(f"\n✅ 文件复制完成:{target_path}")
  29. # 测试
  30. if __name__ == "__main__":
  31. source = "F:/BaiduNetdiskDownload/ubuntu-24.10-desktop-amd64.iso"
  32. target = "D:/bat/ubuntu_with_progress.iso"
  33. copy_file_with_progress(source, target)
复制代码

4.3 文件复制常见问题

  • 路径问题:Windows 路径分隔符可用 \\(转义)或 /(推荐);目标路径必须包含文件名。

  • 权限问题:操作系统目录需管理员权限。

  • 大文件处理:分块大小推荐 1MB~8MB,平衡速度与内存。

5 抽象数据的 IO 操作(序列化与反序列化)

抽象数据:列表、字典、元组等非字符 / 字节类型。

  • 序列化:对象 → 文件可存储格式

  • 反序列化:文件 → 原始对象

5.1 pickle 模块(字节序列化,支持所有 Python 对象)

5.1.1 序列化(对象 → 字节文件)

  1. import pickle
  2. # 准备抽象数据(字典、列表混合)
  3. user_data = {
  4. "admin": {"username": "admin", "password": "123456", "age": 25},
  5. "manager": {"username": "manager", "password": "654321", "roles": ["user", "admin"]}
  6. }
  7. # 序列化到字节文件(mode="wb")
  8. with open("user_data.dat", mode="wb") as file:
  9. pickle.dump(user_data, file) # dump():将对象写入文件
  10. print("✅ 数据序列化完成")
复制代码

5.1.2 反序列化(字节文件 → 对象)

  1. import pickle
  2. # 从字节文件反序列化
  3. with open("user_data.dat", mode="rb") as file:
  4. loaded_data = pickle.load(file) # load():读取文件并恢复对象
  5. # 验证数据(类型和内容不变)
  6. print("反序列化后数据类型:", type(loaded_data))
  7. print("反序列化后数据:", loaded_data)
  8. print("admin 密码:", loaded_data["admin"]["password"])
复制代码

5.2 json 模块(字符序列化,跨语言兼容)

5.2.1 序列化(对象 → JSON 文件)

  1. import json
  2. # 准备基础抽象数据(仅支持 JSON 兼容类型)
  3. product_data = {
  4. "id": 1001,
  5. "name": "Python 编程从入门到实践",
  6. "price": 89.0,
  7. "tags": ["编程", "Python", "入门"],
  8. "is_stock": True
  9. }
  10. # 序列化到 JSON 文件(mode="wt",指定 encoding)
  11. with open("product.json", mode="wt", encoding="UTF-8") as file:
  12. # indent:格式化输出;ensure_ascii=False:支持中文
  13. json.dump(product_data, file, indent=4, ensure_ascii=False)
  14. print("✅ JSON 序列化完成")
复制代码

5.2.2 反序列化(JSON 文件 → 对象)

  1. import json
  2. # 从 JSON 文件反序列化
  3. with open("product.json", encoding="UTF-8") as file:
  4. loaded_product = json.load(file)
  5. print("反序列化后数据类型:", type(loaded_product))
  6. print("产品名称:", loaded_product["name"])
  7. print("产品标签:", loaded_product["tags"])
复制代码

5.3 序列化模块对比

模块序列化格式支持数据类型跨语言兼容适用场景
pickle字节流所有 Python 对象否(仅 Python)内部数据持久化
jsonJSON 字符串基础类型跨语言交互
marshal字节流基础类型了解即可
shelve数据库文件字典格式简单键值存储

6 综合任务代码

6.1 任务 1:文本文件合并工具(按文件名顺序)

  1. import os
  2. def merge_txt_files(output_filename="合并结果.txt"):
  3. all_files = os.listdir(".")
  4. txt_files = [f for f in all_files if f.endswith(".txt")]
  5. if not txt_files:
  6. print("当前目录没有找到任何 .txt 文件!")
  7. return
  8. txt_files.sort()
  9. print(f"即将合并以下文件:{txt_files}")
  10. with open(output_filename, "w", encoding="utf-8") as out_file:
  11. for file in txt_files:
  12. try:
  13. with open(file, "r", encoding="utf-8") as in_file:
  14. out_file.write(f"===== 来自文件:{file} =====\n")
  15. out_file.write(in_file.read())
  16. out_file.write("\n\n")
  17. print(f"已合并:{file}")
  18. except Exception as e:
  19. print(f"读取文件 {file} 失败:{e}")
  20. print(f"\n✅ 合并完成!结果保存在:{output_filename}")
  21. if __name__ == "__main__":
  22. merge_txt_files()
复制代码

6.2 任务 2:JSON 用户信息管理系统

  1. import json
  2. import os
  3. USER_FILE = "users.json"
  4. class UserManager:
  5. def __init__(self):
  6. self.users = []
  7. self.load_from_file()
  8. def add_user(self, user_id, name, age, phone):
  9. for user in self.users:
  10. if user["id"] == user_id:
  11. print("❌ 用户ID已存在!")
  12. return False
  13. new_user = {"id": user_id, "name": name, "age": age, "phone": phone}
  14. self.users.append(new_user)
  15. print("✅ 用户添加成功")
  16. return True
  17. def find_user(self, user_id):
  18. for user in self.users:
  19. if user["id"] == user_id:
  20. return user
  21. return None
  22. def save_to_file(self):
  23. with open(USER_FILE, "w", encoding="utf-8") as f:
  24. json.dump(self.users, f, ensure_ascii=False, indent=4)
  25. print("✅ 数据已保存到 users.json")
  26. def load_from_file(self):
  27. if os.path.exists(USER_FILE):
  28. with open(USER_FILE, "r", encoding="utf-8") as f:
  29. self.users = json.load(f)
  30. print(f"✅ 从文件加载了 {len(self.users)} 条用户数据")
  31. else:
  32. self.users = []
  33. if __name__ == "__main__":
  34. um = UserManager()
  35. um.add_user(101, "张三", 20, "13800138000")
  36. um.add_user(102, "李四", 22, "13900139000")
  37. user = um.find_user(101)
  38. print("\n查询结果:", user)
  39. um.save_to_file()
复制代码

6.3 任务 3:支持断点续传的文件复制

  1. import os
  2. import json
  3. RECORD_FILE = "copy_record.json"
  4. class ResumableCopy:
  5. def __init__(self, source, target, chunk_size=1024*1024):
  6. self.source = source
  7. self.target = target
  8. self.chunk_size = chunk_size
  9. self.record = self.load_record()
  10. def load_record(self):
  11. if os.path.exists(RECORD_FILE):
  12. with open(RECORD_FILE) as f:
  13. return json.load(f)
  14. return {}
  15. def save_record(self, position):
  16. self.record[self.source] = position
  17. with open(RECORD_FILE, "w") as f:
  18. json.dump(self.record, f, indent=2)
  19. def start_copy(self):
  20. if not os.path.exists(self.source):
  21. print("❌ 源文件不存在")
  22. return
  23. total_size = os.path.getsize(self.source)
  24. start_pos = self.record.get(self.source, 0)
  25. if start_pos >= total_size:
  26. print("✅ 文件已完整复制,无需继续")
  27. if self.source in self.record:
  28. del self.record[self.source]
  29. self.save_record(0)
  30. return
  31. print(f"⏯️ 从断点 {start_pos} 字节处继续复制")
  32. with open(self.source, "rb") as src, open(self.target, "ab") as tgt:
  33. src.seek(start_pos)
  34. while True:
  35. chunk = src.read(self.chunk_size)
  36. if not chunk:
  37. break
  38. tgt.write(chunk)
  39. start_pos += len(chunk)
  40. self.save_record(start_pos)
  41. print(f"\r复制进度:{start_pos / total_size * 100:.1f}%", end="")
  42. print("\n✅ 复制完成!")
  43. if self.source in self.record:
  44. del self.record[self.source]
  45. self.save_record(0)
  46. if __name__ == "__main__":
  47. copy = ResumableCopy(source="大文件.zip", target="大文件_副本.zip")
  48. copy.start_copy()
复制代码

推荐在线正则测试工具:

1.Regex101.htm(支持语法提示、匹配结果实时预览)

2.菜鸟工具-正则表达式测试

第二部分 正则表达式

1 认识正则表达式

1.1 核心概念

  • 正则表达式(Regular Expression):简称 regex/regexp,是一种用于匹配、查找、替换文本的模式语言。

  • 核心价值:用简洁的表达式描述复杂的文本规则,高效处理字符串(匹配验证、提取筛选、替换清洗)。

  • 适用场景:表单验证(手机号、邮箱)、日志分析、数据爬虫、文本编辑器查找替换等。

1.2 正则表达式的优势

处理方式实现逻辑代码复杂度灵活性效率
普通字符串方法(in/split ()/replace ())逐字符比对,需手动组合逻辑高(复杂规则需多步判断)低(仅支持固定匹配)简单场景高效
正则表达式编译模式后批量匹配,支持复杂规则低(一行表达式搞定复杂规则)高(支持模糊匹配、动态规则)复杂场景高效

1.3 简单示例

需求正则表达式匹配结果
匹配手机号(11 位数字,以 13/14/15/17/18/19 开头)^1[3-9]\d{9}$匹配:13800138000,不匹配:12345678901/1380013800
匹配邮箱(以字母 / 数字开头,支持 @xx.com/xx.cn 等)^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z]{2,6}$匹配:test123@qq.com,不匹配:test@.com/test#163.cn
提取文本中的所有数字\d+文本:abc123def45.67 → 提取:123/45/67

2 正则表达式基础语法

正则表达式的核心是元字符(具有特殊含义的字符),通过元字符组合成匹配规则。

2.1 元字符分类与说明

2.1.1 匹配单个字符的元字符

元字符功能示例匹配结果
.匹配任意单个字符(除换行符 \n)a.b匹配:acb/a+b/a b,不匹配:abb/a\nb
[]匹配括号内的任意一个字符[abc]匹配:a/b/c
[^]匹配括号外的任意一个字符(取反)[^abc]匹配:d/1/!,不匹配:a/b/c
\d匹配任意数字(等价于 [0-9])\d匹配:0/5/9
\D匹配非数字(等价于 [^0-9])\D匹配:a/!/,不匹配:0-9
\w匹配字母、数字、下划线(等价于 [a-zA-Z0-9_])\w匹配:A/3/_,不匹配:!/@/
\W匹配非字母、数字、下划线\W匹配:!/@/,不匹配:a-zA-Z0-9_
\s匹配空白字符(空格、制表符 \t、换行符 \n 等)a\sb匹配:a b/a\tb,不匹配:ab/a_b
\S匹配非空白字符a\Sb匹配:acb/a_b,不匹配:a b/a\tb
\b单词边界(匹配单词开头 / 结尾,无实际字符)\bhello\b匹配:hello world/say hello,不匹配:helloworld/hello_123
\B非单词边界\Bhello\B匹配:helloworld/hello_123,不匹配:hello world

2.1.2 匹配数量的量词(限定前面元字符的出现次数)

量词功能示例匹配结果
*匹配前面的元字符 0 次或多次(贪婪)ab*匹配:a/ab/abb/abbb
+匹配前面的元字符 1 次或多次(贪婪)ab+匹配:ab/abb/abbb,不匹配:a
?匹配前面的元字符 0 次或 1 次(贪婪)ab?匹配:a/ab,不匹配:abb
{n}匹配前面的元字符恰好 n 次a{3}匹配:aaa,不匹配:aa/aaaa
{n,}匹配前面的元字符至少 n 次(贪婪)a{2,}匹配:aa/aaa/aaaa,不匹配:a
{n,m}匹配前面的元字符 n~m 次(贪婪)a{2,4}匹配:aa/aaa/aaaa,不匹配:a/aaaaa

2.1.3 匹配位置的锚定符(不匹配字符,仅匹配位置)

锚定符功能示例匹配结果
^匹配字符串开头(多行模式下匹配每行开头)^hello匹配:hello world,不匹配:world hello
$匹配字符串结尾(多行模式下匹配每行结尾)world$匹配:hello world,不匹配:world hello
\A匹配字符串绝对开头(不受多行模式影响)\Ahello仅匹配:hello world(字符串首字符为 h)
\Z匹配字符串绝对结尾(不受多行模式影响)world\Z仅匹配:hello world(字符串尾字符为 d)

2.1.4 分组与逻辑运算符

符号功能示例匹配结果
()分组(将多个元字符视为一个整体,支持捕获)(ab)+匹配:ab/abab/ababab
``逻辑或(匹配任意一个分组)`abcdef`匹配:abc/def,不匹配:abd/cde
\num反向引用(引用第 num 个分组的匹配结果)(\w+)\s+\1匹配:hello hello/123 123,不匹配:hello world
(?:)非捕获分组(仅分组,不捕获结果,节省资源)(?:ab)+匹配:ab/abab,但无法通过 \1 引用

2.2 转义字符(\)

当需要匹配元字符本身(如 ./*/()时,需用 \ 转义:

  • 匹配 .:\.(如 192\.168\.1\.1 匹配 IP 地址中的点)

  • 匹配 *:\*(如 a\*b 匹配 a*b)

  • 匹配 (:\(`(如 `\(123\) 匹配 (123))

2.3 常用正则表达式

需求正则表达式说明
手机号^1[3-9]\d{9}$11 位数字,以 13/14/15/17/18/19 开头
固定电话^0\d{2,3}-\d{7,8}$格式:010-12345678 / 0571-87654321
邮箱^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z]{2,6}$支持常见域名(.com/.cn/.org 等)
身份证号(18 位)^[1-9]\d{16}[\dXx]$最后一位可为数字或 X/x
IP 地址(IPv4)`^((25[0-5]2[0-4]\d[01]?\d\d?).){3}(25[0-5]2[0-4]\d[01]?\d\d?)$`匹配合法 IPv4 地址
中文汉字^[\u4e00-\u9fa5]+$仅匹配纯中文(不含字母、数字、符号)
强密码^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{8,16}$含大小写、数字、符号,8-16 位
URL`^(https?ftp)://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$`匹配 http/https/ftp 网址

3 Python re 模块

Python 内置 re 模块提供正则表达式的核心操作。

3.1 re 模块函数

函数功能返回值关键说明
re.match()从字符串开头匹配匹配对象 / None仅匹配开头
re.search()任意位置首次匹配匹配对象 / None扫描整个字符串
re.findall()提取所有匹配结果列表无匹配返回空列表
re.finditer()提取所有匹配(迭代器)迭代器大量结果节省内存
re.sub()替换匹配内容新字符串支持字符串 / 函数替换
re.split()按模式分割字符串列表支持自定义分割符
re.compile()编译正则模式模式对象多次复用提高效率

3.2 匹配对象常用方法

方法功能示例
group()返回整个匹配字符串match.group() → 123
group(n)返回第 n 个分组match.group(1) → 2024
groups()返回所有分组(元组)('2024','10','01')
start()匹配起始索引0
end()匹配结束索引7
span()匹配索引范围(0,7)

3.3 实战示例

3.3.1 re.match () 从开头匹配

  1. import re
  2. pattern = r'^1[3-9]\d{9}$'
  3. string1 = '13800138000'
  4. string2 = 'tel:13800138000'
  5. print(re.match(pattern, string1).group())
  6. print(re.match(pattern, string2))
复制代码

3.3.2 re.search () 首次匹配

  1. pattern = r'\d+'
  2. string = 'abc123def456'
  3. print(re.search(pattern, string).group())
复制代码

3.3.3 re.findall () 提取所有

  1. pattern = r'\d+\.?\d*'
  2. string = '价格:99元,折扣:0.85,最终价格:84.15元'
  3. print(re.findall(pattern, string))
复制代码

3.3.4 re.sub () 替换内容

  1. # 敏感词替换
  2. pattern = r'垃圾'
  3. string = '这个产品真垃圾!垃圾商家!'
  4. print(re.sub(pattern, '***', string))
  5. # 函数替换
  6. def add_brackets(match):
  7. return f'({match.group()})'
  8. pattern = r'\d+'
  9. string = 'a123b456c'
  10. print(re.sub(pattern, add_brackets, string))
复制代码

3.3.5 re.split () 分割字符串

  1. pattern = r'\s+'
  2. string = 'hello world\tpython\nregex'
  3. print(re.split(pattern, string))
复制代码

3.3.6 re.compile () 编译复用

  1. pattern = re.compile(r'[a-zA-Z]+')
  2. string1 = '123abc456def'
  3. string2 = '789ghi012jkl'
  4. print(pattern.findall(string1))
  5. print(pattern.findall(string2))
复制代码

3.4 flags 模式修饰符

flags 值功能示例
re.I忽略大小写re.search(r'abc','ABC',re.I)
re.M多行模式^/$ 匹配每行开头结尾
re.S单行模式. 匹配换行
re.X允许注释空格复杂正则可读性更高

示例:

  1. pattern = r'''
  2. ^1[3-9]
  3. \d{9}$
  4. '''
  5. string = '13800138000'
  6. print(re.match(pattern, string, re.X).group())
复制代码

4 正则表达式高级用法

4.1 贪婪匹配与非贪婪匹配

  • 贪婪:尽可能多匹配(默认)

  • 非贪婪:量词后加 ?,尽可能少匹配

表达式文本贪婪结果非贪婪结果
a.*baabcbcdaabcb-
a.*?baabcbcd-aab

示例:

  1. html = '<div>正则</div><div>实战</div>'
  2. greedy = r'<div.*</div>'
  3. non_greedy = r'<div.*?</div>'
  4. print(re.findall(greedy, html))
  5. print(re.findall(non_greedy, html))
复制代码

4.2 分组与反向引用

4.2.1 捕获分组

  1. pattern = r'(\d{4})-(\d{2})-(\d{2})'
  2. string = '2024-10-01'
  3. res = re.search(pattern, string)
  4. print(res.group(1), res.group(2), res.group(3))
复制代码

4.2.2 反向引用

  1. pattern = r'(\w+)\s+\1'
  2. print(re.search(pattern, 'hello hello').group())
复制代码

4.2.3 非捕获分组

  1. pattern = r'(?:ab)+'
  2. print(re.search(pattern, 'abab').group())
复制代码

4.3 零宽断言(位置匹配)

断言功能示例
(?=pattern)后面满足a(?=b)
(?!pattern)后面不满足a(?!b)
(?<=pattern)前面满足(?<=a)b
(?前面不满足(?

示例:

  1. pattern = r'\d+\.?\d*(?=元)'
  2. string = '价格:99元,折扣价:84.5元'
  3. print(re.findall(pattern, string))
复制代码

5 常见场景案例

5.1 表单验证(手机号 + 邮箱)

  1. import re
  2. def validate_phone(phone):
  3. return bool(re.match(r'^1[3-9]\d{9}$', phone))
  4. def validate_email(email):
  5. return bool(re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z]{2,6}$', email))
复制代码

5.2 日志分析(提取 IP、时间)

  1. log = '''192.168.1.1 - - [01/Oct/2024:12:00:00 +0800] "GET /index.html" 200'''
  2. pattern = r'(\d+\.\d+\.\d+\.\d+).*?\[([^\]]+)\] "(\w+) ([^"]+)" (\d+)'
  3. for res in re.findall(pattern, log):
  4. print(f"IP:{res[0]}, 时间:{res[1]}")
复制代码

5.3 文本清洗(去 HTML、多余空格)

  1. def clean_text(text):
  2. text = re.sub(r'<[^>]+>', '', text)
  3. text = re.sub(r'\s+', ' ', text).strip()
  4. return text
复制代码

5.4 提取图片 URL

  1. html = '<img src="https://example.com/img1.jpg">'
  2. pattern = r'<img.*?src="([^"]+)"'
  3. print(re.findall(pattern, html))
复制代码

6 正则表达式常见误区

6.1 误区 1:忘记转义元字符

  • 错误:192.168.1.1

  • 正确:192\.168\.1\.1

6.2 误区 2:混淆 ^/$ 与 \A/\Z

  • ^/$ 受多行模式影响

  • \A/\Z 始终匹配整个字符串

6.3 误区 3:过度使用贪婪匹配

  • 提取标签优先使用 .*?

6.4 误区 4:忽略大小写与换行

  • 忽略大小写:re.I

  • 匹配换行:re.S

6.5 性能优化

  • 多次使用:re.compile()

  • 复杂分组:非捕获分组 (?:)

  • 大数据:re.finditer()

7 任务代码

7.1 任务 1:身份证验证 + 提取生日

  1. import re
  2. def check_id_card(id_str):
  3. pattern = r'^[1-9]\d{16}[\dXx]$'
  4. if not re.fullmatch(pattern, id_str):
  5. return False, "格式错误"
  6. birth = id_str[6:14]
  7. return True, f"{birth[:4]}-{birth[4:6]}-{birth[6:8]}"
复制代码

7.2 任务 2:提取 URL 域名

  1. import re
  2. def get_domain_from_url(url):
  3. res = re.search(r'https?://([^/]+)', url)
  4. return res.group(1) if res else None
复制代码

7.3 任务 3:清洗纯中文文本

  1. import re
  2. def clean_chinese_text(text):
  3. text = re.sub(r'<[^>]+>', '', text)
  4. return re.sub(r'[^\u4e00-\u9fa5,。!?;:“”‘’()【】]', '', text).strip()
复制代码

7.4 任务 4:手机号脱敏

  1. import re
  2. def mask_phone(phone):
  3. return re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', phone)
复制代码

第三部分 Python进阶

1 文件操作进阶

文件操作是 Python 数据处理与项目开发的基础,进阶内容聚焦 非文本文件处理、大文件高效处理、路径灵活适配 三大核心场景,解决基础文件操作的局限性。

1.1 二进制文件读写

适用于图片、视频、音频、压缩包等非文本文件,核心是通过二进制模式(rb/wb/ab)操作数据,保留文件原始字节信息。

1.1.1 核心模式说明

模式功能适用场景
rb二进制读模式读取图片、视频等非文本文件
wb二进制写模式(覆盖)保存图片、生成二进制文件
ab二进制追加模式向二进制文件追加内容

1.1.2 实战案例:通用文件复制

  1. """
  2. 二进制文件复制:支持图片、视频、音频等所有文件类型
  3. 核心:按字节读取和写入,保留文件原始数据
  4. """
  5. def copy_binary_file(src_path, dst_path):
  6. try:
  7. with open(src_path, "rb") as f_in, open(dst_path, "wb") as f_out:
  8. data = f_in.read()
  9. f_out.write(data)
  10. print(f"文件复制成功:{src_path} → {dst_path}")
  11. except FileNotFoundError:
  12. print(f"错误:源文件 {src_path} 不存在")
  13. except PermissionError:
  14. print(f"错误:无权限访问文件")
  15. except Exception as e:
  16. print(f"文件复制失败:{str(e)}")
  17. # 调用
  18. copy_binary_file("input.jpg", "output.jpg")
复制代码

1.2 大文件分块处理

文件体积过大(1GB 以上)时,一次性读取会导致内存溢出,分块处理实现逐块读取 - 逐块写入,高效复用内存。

1.2.1 实战案例:大文件分块复制

  1. """
  2. 大文件分块复制:适用于 GB 级文件,避免内存溢出
  3. chunk_size:分块大小,1024*1024 = 1MB
  4. """
  5. def copy_large_file(src_path, dst_path, chunk_size=1024*1024):
  6. try:
  7. with open(src_path, "rb") as f_in, open(dst_path, "wb") as f_out:
  8. while True:
  9. chunk = f_in.read(chunk_size)
  10. if not chunk:
  11. break
  12. f_out.write(chunk)
  13. print(f"大文件复制成功:{src_path} → {dst_path}")
  14. except Exception as e:
  15. print(f"大文件复制失败:{str(e)}")
  16. # 调用
  17. copy_large_file("large_video.mp4", "copy_video.mp4")
复制代码

1.2.2 分块大小选型建议

文件大小推荐分块大小内存占用
100MB 以内1MB约 1MB
1GB~5GB4MB~8MB约 4MB~8MB
5GB 以上16MB约 16MB

1.3 路径处理与目录遍历

通过 os 模块实现路径动态拼接、目录遍历,适配 Windows/Linux/Mac 系统。

1.3.1 路径函数

函数功能
os.path.join()动态拼接路径
os.path.exists()判断路径是否存在
os.makedirs()创建目录
os.walk()递归遍历目录

1.3.2 实战案例 1:动态路径与目录创建

  1. import os
  2. base_dir = "project_data"
  3. log_dir = os.path.join(base_dir, "logs")
  4. data_file = os.path.join(base_dir, "user_data.txt")
  5. if not os.path.exists(log_dir):
  6. os.makedirs(log_dir)
  7. print(f"目录创建成功:{log_dir}")
  8. with open(data_file, "w", encoding="utf-8") as f:
  9. f.write("用户数据:动态路径测试")
复制代码

1.3.3 实战案例 2:递归查找 .py 文件

  1. import os
  2. def find_py_files(root_dir):
  3. py_files = []
  4. for root, dirs, files in os.walk(root_dir):
  5. for file in files:
  6. if file.endswith(".py"):
  7. full_path = os.path.join(root, file)
  8. py_files.append(full_path)
  9. return py_files
  10. # 调用
  11. py_list = find_py_files(".")
  12. for file in py_list:
  13. print(file)
复制代码

2 异常处理进阶

聚焦 自定义异常、多异常精准捕获、异常链追溯,适配复杂业务错误处理。

2.1 自定义异常类

继承 Exception 实现业务专属异常,提升错误信息可读性。

2.1.1 定义自定义异常

  1. class BusinessError(Exception):
  2. """业务逻辑异常"""
  3. def __init__(self, code, message):
  4. self.code = code
  5. self.message = message
  6. super().__init__(f"错误码:{code},错误信息:{message}")
  7. class DataFormatError(BusinessError):
  8. """数据格式异常"""
  9. def __init__(self, field):
  10. super().__init__(400, f"数据格式错误:字段 {field} 不合法")
复制代码

2.1.2 抛出与捕获

  1. def process_user_data(data):
  2. if not data:
  3. raise BusinessError(400, "用户数据不能为空")
  4. if "name" not in data:
  5. raise DataFormatError("name")
  6. return f"处理成功:{data['name']}"
  7. try:
  8. process_user_data({"age": 18})
  9. except DataFormatError as e:
  10. print(f"数据异常:{e.message}")
  11. except BusinessError as e:
  12. print(f"业务异常:{e.message}")
复制代码

2.2 多异常精准捕获

遵循 从具体到通用 原则,避免异常覆盖。

  1. try:
  2. data = int(input("请输入数字:"))
  3. result = 10 / data
  4. except ValueError:
  5. print("错误:请输入有效整数")
  6. except ZeroDivisionError:
  7. print("错误:除数不能为零")
  8. except Exception as e:
  9. print(f"未知错误:{e}")
  10. else:
  11. print(f"结果:{result}")
  12. finally:
  13. print("执行完毕")
复制代码

2.3 异常链处理(Python 3.11+)

raise ... from ... 保留异常上下文,快速定位根源。

  1. def read_config(file_path):
  2. try:
  3. with open(file_path, "r", encoding="utf-8") as f:
  4. return f.read()
  5. except FileNotFoundError as e:
  6. e.add_note(f"路径:{file_path}")
  7. raise BusinessError(500, "配置文件读取失败") from e
复制代码

3 模块化开发进阶

核心:高内聚、低耦合,解决大型项目模块混乱、依赖冲突问题。

3.1 包的导入优化

通过 __init__.py 控制导入行为,简化调用。

3.1.1 init.py 配置

  1. # my_package/__init__.py
  2. from .module1 import func1, Class1
  3. from .module2 import func2
  4. from .utils.helper import format_data
  5. __all__ = ["func1", "Class1", "func2", "format_data"]
  6. PACKAGE_VERSION = "1.0.0"
复制代码

3.1.2 简化导入效果

  1. # 优化后
  2. from my_package import func1, format_data
复制代码

3.2 绝对导入与相对导入

导入方式优点适用场景
绝对导入路径清晰、跨包支持大型多包项目
相对导入无需硬编码包名单包内部交互
  1. # 绝对导入
  2. from package_a.module_a import func_a
  3. # 相对导入
  4. from .module1 import func1
  5. from ..module1 import func1
复制代码

3.3 模块依赖管理

使用 requirements.txt 管理第三方依赖。

  1. # 导出依赖
  2. pip freeze > requirements.txt
  3. # 安装依赖
  4. pip install -r requirements.txt
复制代码

3.4 跨文件数据共享

优先使用配置模块 / 配置类,避免全局变量。

3.4.1 配置模块(config.py)

  1. APP_NAME = "实战项目"
  2. DB_CONFIG = {"host": "127.0.0.1", "port": 3306}
复制代码

3.4.2 配置类(面向对象)

  1. class AppConfig:
  2. def __init__(self):
  3. self.app_name = "实战项目"
  4. self.debug = True
  5. config = AppConfig()
复制代码

4 综合实战:文件处理工具包

4.1 项目结构

  1. file_toolkit/
  2. ├── __init__.py
  3. ├── file_operate.py
  4. ├── path_utils.py
  5. ├── config_reader.py
  6. ├── logger.py
  7. └── config.json
复制代码

4.2 核心模块代码

4.2.1 日志模块(logger.py)

  1. import logging, os
  2. from datetime import datetime
  3. def setup_logger():
  4. log_dir = "logs"
  5. os.makedirs(log_dir, exist_ok=True)
  6. log_file = os.path.join(log_dir, f"{datetime.now():%Y-%m-%d}.log")
  7. formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
  8. logger = logging.getLogger("file_toolkit")
  9. logger.addHandler(logging.FileHandler(log_file, encoding="utf-8"))
  10. logger.addHandler(logging.StreamHandler())
  11. return logger
  12. logger = setup_logger()
复制代码

4.2.2 文件操作模块(file_operate.py)

  1. import os
  2. from .logger import logger
  3. def copy_file(src_path, dst_path, chunk_size=1024*1024):
  4. try:
  5. with open(src_path, "rb") as f_in, open(dst_path, "wb") as f_out:
  6. while chunk := f_in.read(chunk_size):
  7. f_out.write(chunk)
  8. logger.info(f"复制成功:{src_path}")
  9. return True
  10. except Exception as e:
  11. logger.error(f"复制失败:{e}")
  12. return False
复制代码

4.2.3 路径工具模块(path_utils.py)

  1. import os
  2. from .logger import logger
  3. def find_files_by_suffix(root_dir, suffix_list):
  4. match_files = []
  5. for root, _, files in os.walk(root_dir):
  6. for f in files:
  7. if f.endswith(tuple(suffix_list)):
  8. match_files.append(os.path.join(root, f))
  9. return match_files
复制代码

4.2.4 配置读取模块(config_reader.py)

  1. import json, os
  2. from .logger import logger
  3. def read_json_config(file_path):
  4. with open(file_path, "r", encoding="utf-8") as f:
  5. return json.load(f)
复制代码

4.2.5 包初始化(init.py)

  1. from .file_operate import copy_file
  2. from .path_utils import find_files_by_suffix
  3. from .config_reader import read_json_config
  4. from .logger import logger
  5. __version__ = "1.0.0"
  6. __all__ = ["copy_file", "find_files_by_suffix", "read_json_config", "logger"]
复制代码

4.3 项目使用示例

  1. from file_toolkit import copy_file, find_files_by_suffix, read_json_config
  2. copy_file("large.mp4", "backup/large.mp4")
  3. files = find_files_by_suffix(".", [".py", ".json"])
  4. config = read_json_config("config.json")
复制代码
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    中国红客联盟公众号

    联系站长QQ:5520533

    admin@chnhonker.com
    Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行