Python 装饰器入门

Python 装饰器入门 装饰器是 Python 的强大特性,可以在不修改原函数的情况下增强其功能。 1. 基本装饰器 def my_decorator(func): def wrapper(): print("调用前") func() print("调用后") return wrapper @my_decorator def say_hello(): print("Hello!") say_hello() # 输出: # 调用前 # Hello! # 调用后 2. 带参数的装饰器 def repeat(times): def decorator(func): def wrapper(*args, **kwargs): for _ in range(times): result = func(*args, **kwargs) return result return wrapper return decorator @repeat(times=3) def say_hi(): print("Hi!") say_hi() 3. 保留原函数信息 from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): print("调用前") return func(*args, **kwargs) return wrapper @my_decorator def greet(name): """问候函数""" return f"Hello, {name}" print(greet.__name__) # greet print(greet.__doc__) # 问候函数 4. 常用内置装饰器 class MyClass: @staticmethod def static_method(): pass @classmethod def class_method(cls): pass @property def prop(self): return self._value 5. 装饰器实际应用 计时装饰器 import time from functools import wraps def timer(func): @wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) print(f"耗时: {time.time() - start:.2f}秒") return result return wrapper @timer def slow_function(): time.sleep(1) 日志装饰器 def log(func): @wraps(func) def wrapper(*args, **kwargs): print(f"调用 {func.__name__}") result = func(*args, **kwargs) print(f"{func.__name__} 返回: {result}") return result return wrapper 缓存装饰器 from functools import lru_cache @lru_cache(maxsize=128) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) 装饰器是 Python 开发中的重要技能,掌握它能写出更优雅的代码。

April 12, 2026

Python 调试技巧

Python 调试技巧 调试是开发的重要技能,本文介绍常用方法。 1. print 调试 # 简单打印 print(f"x = {x}") print(f"result = {result}") # 条件打印 if result: print(f"Debug: got result {result}") 2. 日志调试 import logging logger = logging.getLogger(__name__) logger.debug(f"variable = {variable}") 3. assertions assert x > 0, "x must be positive" assert isinstance(result, list), "result should be list" 4. pdb 调试器 import pdb # 设置断点 pdb.set_trace() # 或 breakpoint() pdb 命令 命令 说明 n 下一步 s 进入函数 p variable 打印变量 c 继续执行 q 退出 5. VS Code 调试 在 VS Code 中按 F5 开始调试,可以设置断点、查看变量。 ...

April 12, 2026

Python 闭包详解

Python 闭包详解 闭包是指能够访问外部作用域变量的函数。 1. 基本闭包 def outer(): x = 10 def inner(): print(x) return inner func = outer() func() # 10 2. 带参数的闭包 def make_multiplier(n): def multiplier(x): return x * n return multiplier double = make_multiplier(2) print(double(5)) # 10 triple = make_multiplier(3) print(triple(5)) # 15 3. 计数器 def make_counter(): count = 0 def counter(): nonlocal count count += 1 return count return counter c = make_counter() c() # 1 c() # 2 c() # 3 4. 装饰器本质 def logger(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}") return func(*args, **kwargs) return wrapper 5. 注意事项 # nonlocal 声明 def outer(): x = 10 def inner(): nonlocal x # 声明修改外部变量 x = 20 inner() print(x) # 20 闭包是函数式编程的重要组成部分。

April 12, 2026

venv、pip、requirements.txt 是什么

venv、pip、requirements.txt 是什么 Python 项目依赖管理的三件套:虚拟环境、包管理器、依赖清单。 1. venv - 虚拟环境 虚拟环境让每个项目有独立的 Python 解释器和依赖,互不干扰。 创建虚拟环境 # 创建 python -m venv myenv # 激活 (Windows) myenv\Scripts\activate # 激活 (macOS/Linux) source myenv/bin/activate # 退出 deactivate 使用 virtualenv(老版本) # 需要先安装 pip install virtualenv # 创建 virtualenv myenv 2. pip - 包管理器 pip 是 Python 内置的包管理器。 常用命令 # 安装包 pip install requests pip install requests==2.28.0 # 指定版本 pip install "requests>=2.0" # 最低版本 pip install -U requests # 升级 # 卸载 pip uninstall requests # 查看 pip list # 已安装的包 pip show requests # 包信息 pip freeze # 已安装包及版本 # 搜索 pip search requests # 已废弃,用 pip index search 国内镜像 # 临时使用 pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple # 设为默认 pip config set global index-url https://pypi.tuna.tsinghua.edu.cn/simple 3. requirements.txt 记录项目依赖的文件。 ...

April 12, 2026

函数参数里的 *args 和 **kwargs

函数参数里的 *args 和 **kwargs Python 函数使用 *args 和 **kwargs 可以接收任意数量的参数,是编写灵活函数的关键。 1. *args - 可变位置参数 *args 将多余的位置参数收集为元组。 基本用法 def sum_all(*args): print(args) # (1, 2, 3, 4, 5) return sum(args) result = sum_all(1, 2, 3, 4, 5) print(result) # 15 参数顺序 def greet(name, *args, greeting="Hello"): print(f"{greeting}, {name}!") if args: print(f"还有: {args}") greet("Alice", "Bob", "Carol", greeting="Hi") # 输出: # Hi, Alice! # 还有: ('Bob', 'Carol') 2. **kwargs - 可变关键字参数 **kwargs 将多余的关键字参数收集为字典。 基本用法 def info(**kwargs): print(kwargs) # {'name': 'Alice', 'age': 25, 'city': 'Beijing'} info(name="Alice", age=25, city="Beijing") 结合使用 def func(required, *args, **kwargs): print(f"必选: {required}") print(f"可选位置: {args}") print(f"可选关键字: {kwargs}") func("必填参数", "可选1", "可选2", key1="value1", key2="value2") # 输出: # 必选: 必填参数 # 可选位置: ('可选1', '可选2') # 可选关键字: {'key1': 'value1', 'key2': 'value2'} 3. 解包传参 使用 * 和 ** 可以将列表/字典解包为参数。 ...

April 12, 2026

列表、元组、字典、集合怎么选

列表、元组、字典、集合怎么选 Python 提供了四种常用的容器类型:列表(list)、元组(tuple)、字典(dict)、集合(set)。本文介绍它们的特性和适用场景,帮助你做出正确选择。 1. 列表(List)——有序可变的序列 列表是最常用的数据结构,适合需要频繁修改的数据集合。 # 创建列表 fruits = ["apple", "banana", "orange"] numbers = [1, 2, 3, 4, 5] mixed = [1, "hello", 3.14, True] # 列表推导式 squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16] evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8] 列表常用操作 fruits = ["apple", "banana"] # 添加元素 fruits.append("orange") # 末尾添加 fruits.insert(1, "grape") # 指定位置插入 fruits.extend(["pear", "kiwi"]) # 批量添加 # 删除元素 fruits.pop() # 末尾删除并返回 fruits.pop(0) # 删除指定位置 fruits.remove("banana") # 删除第一个匹配项 del fruits[0] # 通过索引删除 # 修改元素 fruits[0] = "watermelon" # 查找 index = fruits.index("banana") # 返回索引 count = fruits.count("apple") # 计数 列表切片 numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] numbers[0] # 0 第一个元素 numbers[-1] # 9 最后一个 numbers[0:5] # [0,1,2,3,4] 切片 numbers[::2] # [0,2,4,6,8] 步长为2 numbers[::-1] # [9,8,7,6,5,4,3,2,1,0] 反转 2. 元组(Tuple)——有序不可变的序列 元组与列表类似,但创建后不能修改,适用于固定数据。 ...

April 12, 2026

文件读写与 pathlib

文件读写与 pathlib Python 3 推荐使用 pathlib 模块处理文件路径,相比传统的 os.path 更加直观。 1. pathilib 基础 from pathlib import Path # 创建路径对象 p = Path("my_folder/file.txt") # 路径拼接 p = Path("my_folder") / "file.txt" # 获取信息 p.name # 'file.txt' 文件名 p.stem # 'file' 无扩展名 p.suffix # '.txt' 扩展名 p.parent # my_folder 父目录 p.exists() # True/False 是否存在 p.is_file() # True/False 是否是文件 p.is_dir() # True/False 是否是目录 2. 读取文件 方法一:read_text / read_bytes from pathlib import Path # 读取文本 content = Path("file.txt").read_text(encoding="utf-8") # 读取二进制 data = Path("image.png").read_bytes() # 读取行 lines = Path("file.txt").read_text().splitlines() 方法二:open 上下文管理器 from pathlib import Path p = Path("file.txt") # 读取全部 with p.open() as f: content = f.read() # 读取一行 with p.open() as f: line = f.readline() # 逐行读取 with p.open() as f: for line in f: print(line.rstrip()) # 读取所有行到列表 with p.open() as f: lines = f.readlines() 3. 写入文件 from pathlib import Path p = Path("output.txt") # 写入文本(覆盖) p.write_text("Hello World", encoding="utf-8") # 写入二进制 p.write_bytes(b"\x00\x01\x02") # 追加写入 with p.open("a", encoding="utf-8") as f: f.write("\n新行") 4. 处理文件夹 from pathlib import Path p = Path("my_folder") # 创建文件夹 p.mkdir(exist_ok=True, parents=True) # 删除文件夹(空目录) p.rmdir() # 列出文件 for item in p.iterdir(): print(item.name) # 递归列出 for item in p.rglob("*.txt"): print(item) # glob 模式匹配 list(Path(".").glob("*.txt")) # 当前目录的 .txt list(Path(".").glob("**/*.py")) # 所有子目录的 .py 5. 文件操作 from pathlib import Path src = Path("source.txt") dst = Path("dest.txt") # 复制 import shutil shutil.copy(src, dst) # 移动 shutil.move(src, dst) # 删除文件 dst.unlink() # 重命名 src.rename("new_name.txt") # 获取文件大小 src.stat().st_size # 修改时间 import time os.utime(src, (time.time(), time.time())) 6. 操作示例 批量重命名 from pathlib import Path folder = Path("images") for p in folder.glob("*.png"): new_name = p.stem.replace(" ", "_") + ".png" p.rename(p.parent / new_name) 查找大文件 from pathlib import Path folder = Path(".") large_files = [] for p in folder.rglob("*"): if p.is_file() and p.stat().st_size > 100_000_000: large_files.append((p.stat().st_size, p)) large_files.sort(reverse=True) for size, p in large_files[:10]: print(f"{size:>10,} {p}") 与 os.path 对照 os.path pathlib os.path.join(a, b) Path(a) / b os.path.exists(p) Path(p).exists() os.path.dirname(p) Path(p).parent os.path.basename(p) Path(p).name os.path.splitext(p) (Path(p).stem, Path(p).suffix) os.listdir(p) list(Path(p).iterdir()) os.walk(p) Path(p).rglob("*") pathlib 是现代 Python 推荐的路径处理方式,代码更简洁易读。

April 12, 2026

正则表达式最常用 10 个写法

正则表达式最常用 10 个写法 正则表达式是处理字符串的强大工具,本文整理 Python 中最常用的 10 种写法。 1. 导入与基础匹配 import re # 查找匹配 text = "我的邮箱是 test@example.com" pattern = r'\w+@\w+\.\w+' result = re.search(pattern, text) print(result.group()) # test@example.com # 查找所有 text = "我有三个邮箱: a@test.com, b@test.com, c@test.com" emails = re.findall(r'\w+@\w+\.\w+', text) print(emails) # ['a@test.com', 'b@test.com', 'c@test.com'] 2. 字符类 [abc] # 匹配字符集合 re.search(r'[aeiou]', "hello") # 匹配 e re.search(r'[0-9]', "a1b2") # 匹配 1 re.search(r'[a-zA-Z]', "Hello") # 匹配 H # 否定字符类 re.search(r'[^0-9]', "123a") # 匹配 a 3. 量词 * + ? text = "aabbbbcccc" re.search(r'a*', text) # a* 零个或多个 → aa re.search(r'a+', text) # a+ 一个或多个 → aa re.search(r'b?', text) # b? 零个或一个 → b (优先一个) # 精确数量 re.search(r'c{3}', text) # c{3} 精确3个 → ccc re.search(r'c{2,4}', text) # c{2,4} 2到4个 → cccc 4. 边界匹配 ^ $ # 行首匹配 re.search(r'^hello', 'hello world') # 匹配 re.search(r'^world', 'hello world') # 不匹配 None # 行尾匹配 re.search(r'world$', 'hello world') # 匹配 re.search(r'hello$', 'hello world') # 不匹配 None # 整个字符串匹配 re.fullmatch(r'hello', 'hello') # 匹配 re.fullmatch(r'hello', 'hello world') # 不匹配 5. 元字符 . \d \w \s # . 任意字符(换行符除外) re.search(r'a.c', 'abc') # abc # \d 数字 [0-9] re.search(r'\d{3}', 'a123b') # 123 # \w 单词字符 [a-zA-Z0-9_] re.search(r'\w+', 'hello_world') # hello_world # \s 空白字符 re.search(r'a\sb', 'a b') # a b # 反义 \D # 非数字 \W # 非单词字符 \S # 非空白字符 6. 分组 () text = "2024-04-12" # 分组提取 match = re.search(r'(\d{4})-(\d{2})-(\d{2})', text) print(match.group(0)) # 2024-04-12 整个匹配 print(match.group(1)) # 2024 年 print(match.group(2)) # 04 月 print(match.group(3)) # 12 日 # 命名分组 match = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', text) print(match.group('year')) # 2024 7. 或运算 | re.search(r'cat|dog', 'I like cat') # cat re.search(r'cat|dog', 'I like dog') # dog # 优先级 re.search(r'(foo|foot)', 'football') # foo 8. 替换 re.sub text = "hello world" # 简单替换 re.sub(r'world', 'python', text) # hello python # 使用分组 re.sub(r'(\w+) (\w+)', r'\2 \1', text) # world hello # 替换函数 def to_upper(match): return match.group(0).upper() re.sub(r'hello', to_upper, text) # HELLO world 9. 编译与旗帜 # 编译复用 pattern = re.compile(r'\d+') pattern.findall('a1b2c3') # ['1', '2', '3'] # 常用旗帜 re.IGNORECASE # 忽略大小写 re.MULTILINE # ^ $ 匹配每行 re.DOTALL # . 匹配换行 re.search(r'hello', 'HELLO', re.IGNORECASE) # 匹配 10. 实用示例 提取手机号 text = "我的电话: 13812345678, 另一个: 13900000000" phones = re.findall(r'1[3-9]\d{9}', text) # ['13812345678', '13900000000'] 提取中文 text = "Hello 你好 World 世界" chinese = re.findall(r'[\u4e00-\u9fff]+', text) # ['你好', '世界'] 密码验证 def validate_password(password): if len(password) < 8: return False if not re.search(r'[A-Za-z]', password): return False if not re.search(r'\d', password): return False return True HTML 标签清理 html = '<p>Hello <b>World</b></p>' clean = re.sub(r'<[^>]+>', '', html) # Hello World 快速对照表 写法 说明 [abc] 匹配 a, b, 或 c [^abc] 不匹配 a, b, c \d 数字 \w 单词字符 ^abc abc 开头 abc$ abc 结尾 a* 零个或多个 a a+ 一个或多个 a a{3} 精确 3 个 a (abc) 分组 正则表达式是文本处理的瑞士军刀,掌握这些常用写法能解决大部分字符串处理问题。

April 12, 2026

用 Python 处理 CSV / Excel 小任务

用 Python 处理 CSV / Excel 小任务 Python 是处理表格数据的利器,本文介绍处理 CSV 和 Excel 文件的常用方法。 1. CSV 处理 使用 csv 模块(标准库) import csv # 读取 CSV with open("data.csv", "r", encoding="utf-8") as f: reader = csv.reader(f) for row in reader: print(row) # 写入 CSV data = [ ["姓名", "年龄", "城市"], ["张三", "25", "北京"], ["李四", "30", "上海"], ] with open("output.csv", "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerows(data) 使用 pandas(推荐) import pandas as pd # 读取 df = pd.read_csv("data.csv") print(df.head()) # 基本操作 df["年龄"].mean() # 平均值 df[df["年龄"] > 25] # 筛选 df.sort_values("年龄") # 排序 2. Excel 处理 读取 Excel import pandas as pd # 读取 Excel 文件 df = pd.read_excel("data.xlsx") df = pd.read_excel("data.xlsx", sheet_name="Sheet1") df = pd.read_excel("data.xlsx", sheet_name=None) # 读取所有 sheet # 读取指定列 df = pd.read_excel("data.xlsx", usecols=[0, 1, 2]) df = pd.read_excel("data.xlsx", usecols="A,C:D") 写入 Excel import pandas as pd # 写入单个 sheet df.to_excel("output.xlsx", index=False) # 写入多个 sheet with pd.ExcelWriter("output.xlsx") as writer: df1.to_excel(writer, sheet_name="Sheet1") df2.to_excel(writer, sheet_name="Sheet2") # 指定列 df.to_excel("output.xlsx", columns=["姓名", "年龄"], index=False) 3. 常用 pandas 操作 数据筛选 import pandas as pd df = pd.read_csv("data.csv") # 按条件筛选 df[df["年龄"] > 25] df[df["城市"].isin(["北京", "上海"])] # 多条件 df[(df["年龄"] > 25) & (df["城市"] == "北京")] 数据转换 # 添加列 df["新列"] = df["列1"] + df["列2"] # 修改列 df["年龄"] = df["年龄"] + 1 # 删除列 df.drop("列名", axis=1) # 重命名列 df.rename(columns={"旧名": "新名"}) 数据统计 df.describe() # 统计摘要 df["列"].value_counts() # 计数 df["列"].unique() # 唯一值 df["列"].drop_duplicates() # 去重 4. 处理大数据 分块读取 import pandas as pd # 读取大文件 for chunk in pd.read_csv("big.csv", chunksize=10000): # 处理每块数据 print(chunk.shape) Excel 样式 import pandas as pd from openpyxl import Workbook from openpyxl.styles import Font, PatternFill # 创建带样式的 Excel wb = Workbook() ws = wb.active # 写入数据 ws.append(["姓名", "年龄"]) ws.append(["张三", 25]) # 设置表头样式 header_font = Font(bold=True, color="FFFFFF") header_fill = PatternFill(start_color="366091", end_color="366091", fill_type="solid") for cell in ws[1]: cell.font = header_font cell.fill = header_fill wb.save("styled.xlsx") 5. 实用示例 CSV 转 Excel import pandas as pd # 读取 CSV df = pd.read_csv("data.csv") # 写入 Excel df.to_excel("data.xlsx", index=False) Excel 多表合并 import pandas as pd # 读取所有 sheet all_sheets = pd.read_excel("data.xlsx", sheet_name=None) # 合并 merged = pd.concat(all_sheets.values(), ignore_index=True) # 保存 merged.to_excel("merged.xlsx", index=False) CSV 去重 import pandas as pd df = pd.read_csv("data.csv") # 按列去重 df_unique = df.drop_duplicates(subset=["邮箱"]) df_unique.to_csv("unique.csv", index=False) 数据分组统计 import pandas as pd df = pd.read_csv("sales.csv") # 分组统计 grouped = df.groupby("产品").agg({ "销售额": "sum", "数量": "mean" }).reset_index() grouped.to_excel("summary.xlsx", index=False) 6. 无 pandas 方案(轻量) openpyxl(纯 Excel) from openpyxl import load_workbook # 读取 wb = load_workbook("data.xlsx") ws = wb.active for row in ws.iter_rows(values_only=True): print(row) # 写入 from openpyxl import Workbook wb = Workbook() ws = wb.active ws.append(["姓名", "年龄"]) ws.append(["张三", 25]) wb.save("output.xlsx") csvkit(万能转换) # 安装 pip install csvkit # CSV 转 Excel csvexport data.xlsx | in2csv data.csv > data.xlsx # Excel 转 CSV in2csv data.xlsx > data.csv # 查看 csvstat data.csv 7. 完整示例 数据处理脚本 #!/usr/bin/env python3 """处理 Excel/CSV 数据的脚本""" import pandas as pd import argparse from pathlib import Path def process_file(input_file, output_file=None): """处理数据文件""" # 读取 suffix = Path(input_file).suffix.lower() if suffix == ".csv": df = pd.read_csv(input_file) elif suffix in [".xlsx", ".xls"]: df = pd.read_excel(input_file) else: raise ValueError(f"不支持的文件格式: {suffix}") print(f"读取 {len(df)} 行数据") # 处理 # ... 这里添加你的处理逻辑 # 写入 output_file = output_file or input_file output_suffix = Path(output_file).suffix.lower() if output_suffix == ".csv": df.to_csv(output_file, index=False) elif output_suffix in [".xlsx", ".xls"]: df.to_excel(output_file, index=False) print(f"已保存到 {output_file}") if __name__ == "__main__": import sys if len(sys.argv) < 2: print("用法: python process.py <输入文件> [输出文件]") sys.exit(1) input_file = sys.argv[1] output_file = sys.argv[2] if len(sys.argv) > 2 else None process_file(input_file, output_file) 使用: ...

April 12, 2026

用 Python 批量改文件名

用 Python 批量改文件名 文件批量重命名是常见需求,本文介绍几种实用的 Python 方案。 1. 基本重命名 使用 pathlib from pathlib import Path folder = Path("images") for p in folder.glob("*.png"): new_name = p.stem.replace(" ", "_") + ".png" p.rename(p.parent / new_name) 使用 os.rename import os folder = "images" for filename in os.listdir(folder): if filename.endswith(".png"): old_path = os.path.join(folder, filename) new_name = filename.replace(" ", "_") new_path = os.path.join(folder, new_name) os.rename(old_path, new_path) 2. 常用重命名模式 添加前缀 from pathlib import Path folder = Path("documents") for p in folder.iterdir(): if p.is_file(): p.rename(p.parent / f"backup_{p.name}") 添加序号 from pathlib import Path folder = Path("photos") for i, p in enumerate(sorted(folder.glob("*.jpg")), start=1): new_name = f"img_{i:03d}{p.suffix}" p.rename(p.parent / new_name) # img_001.jpg, img_002.jpg, ... 统一扩展名 from pathlib import Path folder = Path("documents") for p in folder.glob("*.JPEG"): p.rename(p.with_suffix(".jpg")) 3. 使用正则表达式 import re from pathlib import Path folder = Path("files") for p in folder.glob("*"): if p.is_file(): # 移除日期前缀 2024-01-01_ new_name = re.sub(r'^\d{4}-\d{2}-\d{2}_', '', p.name) if new_name != p.name: p.rename(p.parent / new_name) 4. 批量重命名函数 import os from pathlib import Path import re def batch_rename( folder: str, pattern: str = "*", rename_func=None, dry_run: bool = True ): """批量重命名文件 Args: folder: 文件夹路径 pattern: 文件匹配模式 rename_func: 重命名函数,接受文件名返回新文件名 dry_run: True 则只打印不实际执行 """ folder = Path(folder) results = [] for p in folder.glob(pattern): if not p.is_file(): continue new_name = rename_func(p.name) if new_name and new_name != p.name: results.append((p.name, new_name)) if not dry_run: p.rename(p.parent / new_name) print(f"重命名: {p.name} -> {new_name}") return results # 使用示例:去除空格 batch_rename("images", "*.png", lambda name: name.replace(" ", "_")) # 使用示例:转小写 batch_rename("images", "*.png", lambda name: name.lower()) # 使用示例:添加日期前缀 from datetime import datetime batch_rename("files", "*", lambda name: f"{datetime.now().strftime('%Y%m%d')}_{name}") 5. 带冲突处理 from pathlib import Path from collections import Counter def safe_rename(folder, pattern, rename_func): """安全重命名,处理文件名冲突""" folder = Path(folder) # 第一步:生成所有新文件名 changes = [] for p in folder.glob(pattern): if p.is_file(): new_name = rename_func(p.name) changes.append((p, new_name)) # 检测冲突 new_names = [c[1] for c in changes] duplicates = [k for k, v in Counter(new_names).items() if v > 1] if duplicates: print(f"警告:以下新文件名会冲突: {duplicates}") return # 执行重命名 for old_path, new_name in changes: if new_name != old_path.name: old_path.rename(old_path.parent / new_name) print(f"{old_path.name} -> {new_name}") # 使用 safe_rename("images", "*.png", lambda n: n.replace(" ", "_")) 6. 实际应用示例 整理下载文件 from pathlib import Path import shutil downloads = Path("/Users/hao/Downloads") # 按文件类型分类 for p in downloads.iterdir(): if not p.is_file(): continue ext = p.suffix.lower().replace(".", "") dest = downloads / ext if not dest.exists(): dest.mkdir() shutil.move(str(p), str(dest / p.name)) print(f"移动 {p.name} -> {dest.name}/") 处理照片 from pathlib import Path from datetime import datetime photos = Path("photos") # 从 EXIF 获取拍摄日期(需要 Pillow) from PIL import Image from PIL.ExifTags import TAGS for p in photos.glob("*.jpg"): try: img = Image.open(p) exif = {TAGS[k]: v for k, v in img._getexif().items() if k in TAGS} date = exif.get("DateTimeOriginal") if date: dt = datetime.strptime(date, "%Y:%m:%d %H:%M:%S") new_name = dt.strftime("%Y%m%d_%H%M%S") + ".jpg" p.rename(p.parent / new_name) print(f"{p.name} -> {new_name}") except: continue 7. 完整脚本示例 #!/usr/bin/env python3 """批量文件重命名工具""" import argparse from pathlib import Path def main(): parser = argparse.ArgumentParser(description="批量重命名文件") parser.add_argument("folder", help="目标文件夹") parser.add_argument("--pattern", default="*", help="文件匹配模式") parser.add_argument("--replace", help="要替换的字符串") parser.add_argument("--with", dest="replacement", help="替换为的字符串") parser.add_argument("--prefix", help="添加前缀") parser.add_argument("--suffix", help="添加后缀") parser.add_argument("--execute", action="store_true", help="实际执行(默认只预览)") args = parser.parse_args() folder = Path(args.folder) for p in folder.glob(args.pattern): if not p.is_file(): continue name = p.name stem = p.stem suffix = p.suffix # 应用转换 if args.replace: new_stem = stem.replace(args.replace, args.replacement or "") else: new_stem = stem if args.prefix: new_stem = args.prefix + new_stem if args.suffix: new_stem = new_stem + args.suffix new_name = new_stem + suffix if new_name != name: print(f"{name} -> {new_name}") if args.execute: p.rename(p.parent / new_name) if __name__ == "__main__": main() 使用: ...

April 12, 2026