Python 标准库
Python 内置标准库概览,涵盖日常开发最高频使用的模块。
re — 正则表达式
核心函数
python
import re
text = "联系方式: alice@example.com 和 bob@test.org"
# re.match — 从开头匹配,不匹配则返回 None
m = re.match(r"联系方式", text)
print(m.group() if m else "无匹配") # 联系方式
# re.search — 搜索整个字符串,返回第一个匹配
m = re.search(r"\w+@\w+\.\w+", text)
print(m.group()) # alice@example.com
# re.findall — 返回所有匹配的列表
emails = re.findall(r"\w+@\w+\.\w+", text)
print(emails) # ['alice@example.com', 'bob@test.org']
# re.finditer — 返回迭代器,每个元素是 Match 对象
for match in re.finditer(r"\w+@\w+\.\w+", text):
print(match.group(), match.span())import re
text = "联系方式: alice@example.com 和 bob@test.org"
# re.match — 从开头匹配,不匹配则返回 None
m = re.match(r"联系方式", text)
print(m.group() if m else "无匹配") # 联系方式
# re.search — 搜索整个字符串,返回第一个匹配
m = re.search(r"\w+@\w+\.\w+", text)
print(m.group()) # alice@example.com
# re.findall — 返回所有匹配的列表
emails = re.findall(r"\w+@\w+\.\w+", text)
print(emails) # ['alice@example.com', 'bob@test.org']
# re.finditer — 返回迭代器,每个元素是 Match 对象
for match in re.finditer(r"\w+@\w+\.\w+", text):
print(match.group(), match.span())分组
python
import re
text = "2024-12-25 和 2025-01-01"
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
for m in re.finditer(pattern, text):
print(m.group()) # 完整匹配 2024-12-25
print(m.group(1)) # 2024
print(m.groups()) # ('2024', '12', '25')
print(m.groupdict()) # {'year': '2024', 'month': '12', 'day': '25'}import re
text = "2024-12-25 和 2025-01-01"
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
for m in re.finditer(pattern, text):
print(m.group()) # 完整匹配 2024-12-25
print(m.group(1)) # 2024
print(m.groups()) # ('2024', '12', '25')
print(m.groupdict()) # {'year': '2024', 'month': '12', 'day': '25'}替换
python
import re
text = "联系方式: alice@example.com"
# re.sub — 替换匹配内容
result = re.sub(r"\w+@\w+\.\w+", "***@***.***", text)
print(result) # 联系方式: ***@***.***
# 使用函数动态替换
def mask_email(match):
name = match.group().split("@")[0]
return f"{name[0]}***@{match.group().split('@')[1]}"
result = re.sub(r"\w+@\w+\.\w+", mask_email, text)
print(result) # 联系方式: a***@example.comimport re
text = "联系方式: alice@example.com"
# re.sub — 替换匹配内容
result = re.sub(r"\w+@\w+\.\w+", "***@***.***", text)
print(result) # 联系方式: ***@***.***
# 使用函数动态替换
def mask_email(match):
name = match.group().split("@")[0]
return f"{name[0]}***@{match.group().split('@')[1]}"
result = re.sub(r"\w+@\w+\.\w+", mask_email, text)
print(result) # 联系方式: a***@example.com贪婪与非贪婪
python
import re
text = "<div>内容1</div><div>内容2</div>"
# 贪婪模式(默认)— 尽可能多匹配
greedy = re.search(r"<div>.*</div>", text)
print(greedy.group()) # <div>内容1</div><div>内容2</div>
# 非贪婪模式 — 尽可能少匹配
non_greedy = re.search(r"<div>.*?</div>", text)
print(non_greedy.group()) # <div>内容1</div>import re
text = "<div>内容1</div><div>内容2</div>"
# 贪婪模式(默认)— 尽可能多匹配
greedy = re.search(r"<div>.*</div>", text)
print(greedy.group()) # <div>内容1</div><div>内容2</div>
# 非贪婪模式 — 尽可能少匹配
non_greedy = re.search(r"<div>.*?</div>", text)
print(non_greedy.group()) # <div>内容1</div>常用正则模式
python
import re
# 邮箱
email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
print(bool(re.match(email_pattern, "test@example.com"))) # True
# 手机号(中国大陆)
phone_pattern = r"^1[3-9]\d{9}$"
print(bool(re.match(phone_pattern, "13800138000"))) # True
# URL
url_pattern = r"^https?://[^\s/$.?#].[^\s]*$"
print(bool(re.match(url_pattern, "https://example.com/path"))) # True
# 中文
chinese_pattern = r"[一-鿿]+"
print(re.findall(chinese_pattern, "Hello 世界 Python 编程")) # ['世界', '编程']
# IP 地址
ip_pattern = r"^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$"
print(bool(re.match(ip_pattern, "192.168.1.1"))) # Trueimport re
# 邮箱
email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
print(bool(re.match(email_pattern, "test@example.com"))) # True
# 手机号(中国大陆)
phone_pattern = r"^1[3-9]\d{9}$"
print(bool(re.match(phone_pattern, "13800138000"))) # True
# URL
url_pattern = r"^https?://[^\s/$.?#].[^\s]*$"
print(bool(re.match(url_pattern, "https://example.com/path"))) # True
# 中文
chinese_pattern = r"[一-鿿]+"
print(re.findall(chinese_pattern, "Hello 世界 Python 编程")) # ['世界', '编程']
# IP 地址
ip_pattern = r"^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$"
print(bool(re.match(ip_pattern, "192.168.1.1"))) # True编译正则
python
import re
# 编译后可复用,提升性能
pattern = re.compile(r"\d{4}-\d{2}-\d{2}")
text = "日期: 2024-12-25, 2025-01-01"
print(pattern.findall(text)) # ['2024-12-25', '2025-01-01']import re
# 编译后可复用,提升性能
pattern = re.compile(r"\d{4}-\d{2}-\d{2}")
text = "日期: 2024-12-25, 2025-01-01"
print(pattern.findall(text)) # ['2024-12-25', '2025-01-01']datetime / time / calendar
datetime
python
from datetime import datetime, date, time, timedelta
# 获取当前时间
now = datetime.now()
print(now) # 2025-01-15 14:30:00.123456
# 构造指定时间
dt = datetime(2024, 12, 25, 10, 30, 0)
print(dt) # 2024-12-25 10:30:00
# 日期运算
today = date.today()
tomorrow = today + timedelta(days=1)
yesterday = today - timedelta(days=1)
print(f"今天: {today}, 明天: {tomorrow}, 昨天: {yesterday}")
# 时间差计算
start = datetime(2024, 1, 1)
end = datetime(2024, 12, 31)
delta = end - start
print(delta.days) # 365
print(delta.total_seconds()) # 31536000.0
# timedelta 参数
td = timedelta(days=7, hours=3, minutes=30)
print(td) # 7 days, 3:30:00from datetime import datetime, date, time, timedelta
# 获取当前时间
now = datetime.now()
print(now) # 2025-01-15 14:30:00.123456
# 构造指定时间
dt = datetime(2024, 12, 25, 10, 30, 0)
print(dt) # 2024-12-25 10:30:00
# 日期运算
today = date.today()
tomorrow = today + timedelta(days=1)
yesterday = today - timedelta(days=1)
print(f"今天: {today}, 明天: {tomorrow}, 昨天: {yesterday}")
# 时间差计算
start = datetime(2024, 1, 1)
end = datetime(2024, 12, 31)
delta = end - start
print(delta.days) # 365
print(delta.total_seconds()) # 31536000.0
# timedelta 参数
td = timedelta(days=7, hours=3, minutes=30)
print(td) # 7 days, 3:30:00格式化
python
from datetime import datetime
now = datetime.now()
# datetime → 字符串
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2025-01-15 14:30:00
print(now.strftime("%Y年%m月%d日 %A")) # 2025年01月15日 Wednesday
print(now.strftime("%I:%M %p")) # 02:30 PM
# 字符串 → datetime
dt = datetime.strptime("2024-12-25 10:30:00", "%Y-%m-%d %H:%M:%S")
print(dt) # 2024-12-25 10:30:00
# 常用格式符
# %Y 四位年份 %y 两位年份 %m 月份 %d 日期
# %H 24小时制 %I 12小时制 %M 分钟 %S 秒
# %A 星期全称 %a 星期缩写 %B 月份全称 %b 月份缩写
# %p AM/PM %z 时区 %f 微秒from datetime import datetime
now = datetime.now()
# datetime → 字符串
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2025-01-15 14:30:00
print(now.strftime("%Y年%m月%d日 %A")) # 2025年01月15日 Wednesday
print(now.strftime("%I:%M %p")) # 02:30 PM
# 字符串 → datetime
dt = datetime.strptime("2024-12-25 10:30:00", "%Y-%m-%d %H:%M:%S")
print(dt) # 2024-12-25 10:30:00
# 常用格式符
# %Y 四位年份 %y 两位年份 %m 月份 %d 日期
# %H 24小时制 %I 12小时制 %M 分钟 %S 秒
# %A 星期全称 %a 星期缩写 %B 月份全称 %b 月份缩写
# %p AM/PM %z 时区 %f 微秒time
python
import time
# 时间戳
print(time.time()) # 1736932200.1234567
# 休眠
print("开始")
time.sleep(1.5) # 暂停 1.5 秒
print("结束")
# 时间戳 ↔ 结构化时间
ts = time.time()
struct_time = time.localtime(ts) # 本地时间
print(struct_time.tm_year, struct_time.tm_mon) # 2025 1
# 性能计时
start = time.perf_counter()
# ... 执行代码 ...
end = time.perf_counter()
print(f"耗时: {end - start:.4f}秒")import time
# 时间戳
print(time.time()) # 1736932200.1234567
# 休眠
print("开始")
time.sleep(1.5) # 暂停 1.5 秒
print("结束")
# 时间戳 ↔ 结构化时间
ts = time.time()
struct_time = time.localtime(ts) # 本地时间
print(struct_time.tm_year, struct_time.tm_mon) # 2025 1
# 性能计时
start = time.perf_counter()
# ... 执行代码 ...
end = time.perf_counter()
print(f"耗时: {end - start:.4f}秒")时区处理 (Python 3.9+)
python
from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# 创建带时区的时间
shanghai = datetime(2024, 12, 25, 10, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
print(shanghai) # 2024-12-25 10:00:00+08:00
# 时区转换
utc_time = shanghai.astimezone(ZoneInfo("UTC"))
print(utc_time) # 2024-12-25 02:00:00+00:00
new_york = shanghai.astimezone(ZoneInfo("America/New_York"))
print(new_york) # 2024-12-24 21:00:00-05:00
# 可用时区列表
import zoneinfo
print(zoneinfo.available_timezones()) # 大量时区名称from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# 创建带时区的时间
shanghai = datetime(2024, 12, 25, 10, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
print(shanghai) # 2024-12-25 10:00:00+08:00
# 时区转换
utc_time = shanghai.astimezone(ZoneInfo("UTC"))
print(utc_time) # 2024-12-25 02:00:00+00:00
new_york = shanghai.astimezone(ZoneInfo("America/New_York"))
print(new_york) # 2024-12-24 21:00:00-05:00
# 可用时区列表
import zoneinfo
print(zoneinfo.available_timezones()) # 大量时区名称calendar
python
import calendar
# 打印月历
print(calendar.month(2025, 1))
# 判断闰年
print(calendar.isleap(2024)) # True
print(calendar.isleap(2023)) # False
# 获取每月天数
print(calendar.monthrange(2024, 2)) # (3, 29) (当月第一天星期几, 当月天数)
# 生成日历迭代器
cal = calendar.Calendar()
for week in cal.monthdayscalendar(2025, 1):
print(week)import calendar
# 打印月历
print(calendar.month(2025, 1))
# 判断闰年
print(calendar.isleap(2024)) # True
print(calendar.isleap(2023)) # False
# 获取每月天数
print(calendar.monthrange(2024, 2)) # (3, 29) (当月第一天星期几, 当月天数)
# 生成日历迭代器
cal = calendar.Calendar()
for week in cal.monthdayscalendar(2025, 1):
print(week)json / csv
json
python
import json
data = {
"name": "张三",
"age": 30,
"skills": ["Python", "Docker", "K8s"],
"active": True,
"salary": None,
}
# 序列化 — Python 对象 → JSON 字符串
json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)
# {
# "name": "张三",
# "age": 30,
# "skills": ["Python", "Docker", "K8s"],
# "active": true,
# "salary": null
# }
# 紧凑输出(不缩进)
print(json.dumps(data, ensure_ascii=False)) # 一行
# 反序列化 — JSON 字符串 → Python 对象
json_input = '{"name": "李四", "age": 25}'
parsed = json.loads(json_input)
print(parsed["name"]) # 李四
# 文件读写
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["name"]) # 张三
# 自定义 JSON 序列化(处理 datetime 等类型)
from datetime import datetime
def json_serializer(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
now = datetime.now()
data = {"event": "meeting", "time": now}
print(json.dumps(data, default=json_serializer))
# {"event": "meeting", "time": "2025-01-15T14:30:00"}import json
data = {
"name": "张三",
"age": 30,
"skills": ["Python", "Docker", "K8s"],
"active": True,
"salary": None,
}
# 序列化 — Python 对象 → JSON 字符串
json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)
# {
# "name": "张三",
# "age": 30,
# "skills": ["Python", "Docker", "K8s"],
# "active": true,
# "salary": null
# }
# 紧凑输出(不缩进)
print(json.dumps(data, ensure_ascii=False)) # 一行
# 反序列化 — JSON 字符串 → Python 对象
json_input = '{"name": "李四", "age": 25}'
parsed = json.loads(json_input)
print(parsed["name"]) # 李四
# 文件读写
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["name"]) # 张三
# 自定义 JSON 序列化(处理 datetime 等类型)
from datetime import datetime
def json_serializer(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
now = datetime.now()
data = {"event": "meeting", "time": now}
print(json.dumps(data, default=json_serializer))
# {"event": "meeting", "time": "2025-01-15T14:30:00"}csv
python
import csv
# reader — 读取 CSV
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # 跳过表头
for row in reader:
print(row) # 每行是一个列表
# writer — 写入 CSV
with open("output.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["姓名", "年龄", "城市"]) # 写表头
writer.writerow(["张三", 30, "北京"])
writer.writerow(["李四", 25, "上海"])
writer.writerows([ # 批量写入
["王五", 35, "广州"],
["赵六", 28, "深圳"],
])
# DictReader — 按字典读取
with open("output.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["姓名"], row["年龄"]) # 按列名访问
# DictWriter — 按字典写入
with open("dict_output.csv", "w", newline="", encoding="utf-8") as f:
fieldnames = ["姓名", "年龄", "城市"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"姓名": "张三", "年龄": 30, "城市": "北京"})
writer.writerow({"姓名": "李四", "年龄": 25, "城市": "上海"})import csv
# reader — 读取 CSV
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # 跳过表头
for row in reader:
print(row) # 每行是一个列表
# writer — 写入 CSV
with open("output.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["姓名", "年龄", "城市"]) # 写表头
writer.writerow(["张三", 30, "北京"])
writer.writerow(["李四", 25, "上海"])
writer.writerows([ # 批量写入
["王五", 35, "广州"],
["赵六", 28, "深圳"],
])
# DictReader — 按字典读取
with open("output.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["姓名"], row["年龄"]) # 按列名访问
# DictWriter — 按字典写入
with open("dict_output.csv", "w", newline="", encoding="utf-8") as f:
fieldnames = ["姓名", "年龄", "城市"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"姓名": "张三", "年龄": 30, "城市": "北京"})
writer.writerow({"姓名": "李四", "年龄": 25, "城市": "上海"})collections
namedtuple
python
from collections import namedtuple
# 定义命名元组
Point = namedtuple("Point", ["x", "y"])
p = Point(10, y=20)
print(p.x, p.y) # 10 20
print(p[0], p[1]) # 10 20(索引也支持)
# 解包
x, y = p
print(x, y) # 10 20
# _make — 从可迭代对象创建
data = [30, 40]
p2 = Point._make(data)
print(p2) # Point(x=30, y=40)
# _asdict — 转为 OrderedDict
print(p._asdict()) # {'x': 10, 'y': 20}from collections import namedtuple
# 定义命名元组
Point = namedtuple("Point", ["x", "y"])
p = Point(10, y=20)
print(p.x, p.y) # 10 20
print(p[0], p[1]) # 10 20(索引也支持)
# 解包
x, y = p
print(x, y) # 10 20
# _make — 从可迭代对象创建
data = [30, 40]
p2 = Point._make(data)
print(p2) # Point(x=30, y=40)
# _asdict — 转为 OrderedDict
print(p._asdict()) # {'x': 10, 'y': 20}defaultdict
python
from collections import defaultdict
# 默认值为列表 — 适合分组
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
count = defaultdict(int)
for w in words:
count[w] += 1
print(dict(count)) # {'apple': 3, 'banana': 2, 'orange': 1}
# 默认值为列表
groups = defaultdict(list)
data = [("水果", "苹果"), ("水果", "香蕉"), ("蔬菜", "白菜")]
for category, item in data:
groups[category].append(item)
print(dict(groups)) # {'水果': ['苹果', '香蕉'], '蔬菜': ['白菜']}
# 默认值为自定义工厂
def default_value():
return {"count": 0, "items": []}
stats = defaultdict(default_value)
stats["a"]["count"] += 1
stats["a"]["items"].append("x")from collections import defaultdict
# 默认值为列表 — 适合分组
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
count = defaultdict(int)
for w in words:
count[w] += 1
print(dict(count)) # {'apple': 3, 'banana': 2, 'orange': 1}
# 默认值为列表
groups = defaultdict(list)
data = [("水果", "苹果"), ("水果", "香蕉"), ("蔬菜", "白菜")]
for category, item in data:
groups[category].append(item)
print(dict(groups)) # {'水果': ['苹果', '香蕉'], '蔬菜': ['白菜']}
# 默认值为自定义工厂
def default_value():
return {"count": 0, "items": []}
stats = defaultdict(default_value)
stats["a"]["count"] += 1
stats["a"]["items"].append("x")Counter
python
from collections import Counter
# 计数
words = ["a", "b", "c", "a", "b", "a"]
counter = Counter(words)
print(counter) # Counter({'a': 3, 'b': 2, 'c': 1})
print(counter["a"]) # 3
print(counter["z"]) # 0(不存在不报错)
# 字符串计数
char_count = Counter("hello world")
print(char_count.most_common(3)) # [('l', 3), ('o', 2), ('h', 1)]
# 运算
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print(c1 + c2) # Counter({'a': 4, 'b': 3})
print(c1 - c2) # Counter({'a': 2}) (只保留正数)
# elements — 展开为元素
c = Counter(a=2, b=1)
print(sorted(c.elements())) # ['a', 'a', 'b']from collections import Counter
# 计数
words = ["a", "b", "c", "a", "b", "a"]
counter = Counter(words)
print(counter) # Counter({'a': 3, 'b': 2, 'c': 1})
print(counter["a"]) # 3
print(counter["z"]) # 0(不存在不报错)
# 字符串计数
char_count = Counter("hello world")
print(char_count.most_common(3)) # [('l', 3), ('o', 2), ('h', 1)]
# 运算
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print(c1 + c2) # Counter({'a': 4, 'b': 3})
print(c1 - c2) # Counter({'a': 2}) (只保留正数)
# elements — 展开为元素
c = Counter(a=2, b=1)
print(sorted(c.elements())) # ['a', 'a', 'b']deque
python
from collections import deque
# 双向队列
dq = deque(["a", "b", "c"], maxlen=5) # maxlen 可选
dq.append("d") # 右侧添加
dq.appendleft("z") # 左侧添加
print(dq) # deque(['z', 'a', 'b', 'c', 'd'])
# 弹出
print(dq.pop()) # 'd'
print(dq.popleft()) # 'z'
# 自动丢弃 — 超过 maxlen 时左侧自动丢弃
limited = deque(maxlen=3)
for i in range(10):
limited.append(i)
print(limited) # deque([7, 8, 9])
# 旋转
dq = deque(range(5))
dq.rotate(2)
print(dq) # deque([3, 4, 0, 1, 2])
dq.rotate(-1)
print(dq) # deque([4, 0, 1, 2, 3])from collections import deque
# 双向队列
dq = deque(["a", "b", "c"], maxlen=5) # maxlen 可选
dq.append("d") # 右侧添加
dq.appendleft("z") # 左侧添加
print(dq) # deque(['z', 'a', 'b', 'c', 'd'])
# 弹出
print(dq.pop()) # 'd'
print(dq.popleft()) # 'z'
# 自动丢弃 — 超过 maxlen 时左侧自动丢弃
limited = deque(maxlen=3)
for i in range(10):
limited.append(i)
print(limited) # deque([7, 8, 9])
# 旋转
dq = deque(range(5))
dq.rotate(2)
print(dq) # deque([3, 4, 0, 1, 2])
dq.rotate(-1)
print(dq) # deque([4, 0, 1, 2, 3])ChainMap
python
from collections import ChainMap
# 合并多个字典(按顺序查找)
defaults = {"theme": "dark", "lang": "en", "debug": False}
user_config = {"lang": "zh", "debug": True}
config = ChainMap(user_config, defaults)
print(config["theme"]) # dark(来自 defaults)
print(config["lang"]) # zh(来自 user_config,优先)
print(config["debug"]) # True
# 新增/修改仅影响第一个字典
config["lang"] = "ja"
print(user_config["lang"]) # ja
# new_child — 添加新层级
runtime_args = {"debug": False}
config = config.new_child(runtime_args)
print(config["debug"]) # Falsefrom collections import ChainMap
# 合并多个字典(按顺序查找)
defaults = {"theme": "dark", "lang": "en", "debug": False}
user_config = {"lang": "zh", "debug": True}
config = ChainMap(user_config, defaults)
print(config["theme"]) # dark(来自 defaults)
print(config["lang"]) # zh(来自 user_config,优先)
print(config["debug"]) # True
# 新增/修改仅影响第一个字典
config["lang"] = "ja"
print(user_config["lang"]) # ja
# new_child — 添加新层级
runtime_args = {"debug": False}
config = config.new_child(runtime_args)
print(config["debug"]) # Falselogging
基本配置
python
import logging
# 快速配置
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logging.debug("调试信息")
logging.info("普通信息")
logging.warning("警告信息")
logging.error("错误信息")
logging.critical("严重错误")import logging
# 快速配置
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logging.debug("调试信息")
logging.info("普通信息")
logging.warning("警告信息")
logging.error("错误信息")
logging.critical("严重错误")Logger / Handler / Formatter 架构
python
import logging
# 创建 Logger
logger = logging.getLogger("my_app")
logger.setLevel(logging.DEBUG)
# 控制台 Handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 文件 Handler
file_handler = logging.FileHandler("app.log", encoding="utf-8")
file_handler.setLevel(logging.DEBUG)
# 格式化器
formatter = logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s - %(filename)s:%(lineno)d - %(message)s"
)
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
# 绑定到 Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 使用
logger.info("应用启动")
logger.error("发生错误", exc_info=True) # 包含异常堆栈import logging
# 创建 Logger
logger = logging.getLogger("my_app")
logger.setLevel(logging.DEBUG)
# 控制台 Handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 文件 Handler
file_handler = logging.FileHandler("app.log", encoding="utf-8")
file_handler.setLevel(logging.DEBUG)
# 格式化器
formatter = logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s - %(filename)s:%(lineno)d - %(message)s"
)
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
# 绑定到 Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 使用
logger.info("应用启动")
logger.error("发生错误", exc_info=True) # 包含异常堆栈日志配置文件 (生产推荐)
python
import logging.config
LOGGING_CONFIG = {
"version": 1,
"formatters": {
"standard": {
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "standard",
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "standard",
"filename": "app.log",
"maxBytes": 10 * 1024 * 1024, # 10MB
"backupCount": 5,
"encoding": "utf-8",
},
},
"root": {
"level": "DEBUG",
"handlers": ["console", "file"],
},
}
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger(__name__)
logger.info("使用 dictConfig 配置日志")import logging.config
LOGGING_CONFIG = {
"version": 1,
"formatters": {
"standard": {
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "standard",
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "standard",
"filename": "app.log",
"maxBytes": 10 * 1024 * 1024, # 10MB
"backupCount": 5,
"encoding": "utf-8",
},
},
"root": {
"level": "DEBUG",
"handlers": ["console", "file"],
},
}
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger(__name__)
logger.info("使用 dictConfig 配置日志")argparse / sys / os
argparse
python
import argparse
parser = argparse.ArgumentParser(description="示例命令行工具")
parser.add_argument("input", help="输入文件路径")
parser.add_argument("-o", "--output", default="out.txt", help="输出文件路径")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
parser.add_argument("--count", type=int, default=1, help="执行次数")
parser.add_argument("--mode", choices=["fast", "slow"], default="fast", help="模式")
args = parser.parse_args()
# 使用: python script.py input.txt -o output.txt -v --count 3 --mode slow
print(f"输入文件: {args.input}")
print(f"输出文件: {args.output}")
print(f"详细模式: {args.verbose}")
print(f"执行次数: {args.count}")
print(f"模式: {args.mode}")import argparse
parser = argparse.ArgumentParser(description="示例命令行工具")
parser.add_argument("input", help="输入文件路径")
parser.add_argument("-o", "--output", default="out.txt", help="输出文件路径")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
parser.add_argument("--count", type=int, default=1, help="执行次数")
parser.add_argument("--mode", choices=["fast", "slow"], default="fast", help="模式")
args = parser.parse_args()
# 使用: python script.py input.txt -o output.txt -v --count 3 --mode slow
print(f"输入文件: {args.input}")
print(f"输出文件: {args.output}")
print(f"详细模式: {args.verbose}")
print(f"执行次数: {args.count}")
print(f"模式: {args.mode}")sys
python
import sys
# 命令行参数
print(f"脚本名: {sys.argv[0]}")
print(f"参数列表: {sys.argv[1:]}")
# 退出程序
# sys.exit(0) # 正常退出
# sys.exit(1) # 异常退出(可附带错误信息)
# Python 搜索路径
for path in sys.path:
print(path) # 包含当前目录、site-packages 等
# 系统信息
print(f"Python 版本: {sys.version}")
print(f"操作系统: {sys.platform}") # win32 / linux / darwin
# 标准输入读取
# for line in sys.stdin:
# print(line.strip())import sys
# 命令行参数
print(f"脚本名: {sys.argv[0]}")
print(f"参数列表: {sys.argv[1:]}")
# 退出程序
# sys.exit(0) # 正常退出
# sys.exit(1) # 异常退出(可附带错误信息)
# Python 搜索路径
for path in sys.path:
print(path) # 包含当前目录、site-packages 等
# 系统信息
print(f"Python 版本: {sys.version}")
print(f"操作系统: {sys.platform}") # win32 / linux / darwin
# 标准输入读取
# for line in sys.stdin:
# print(line.strip())os
python
import os
# 环境变量
print(os.environ.get("HOME", "默认值"))
print(os.environ.get("PATH"))
# 设置环境变量(仅影响当前进程)
os.environ["MY_VAR"] = "hello"
# 目录操作
print(os.getcwd()) # 当前工作目录
os.makedirs("a/b/c", exist_ok=True) # 递归创建目录
os.remove("temp.txt") # 删除文件
# 路径操作(推荐 pathlib 替代)
print(os.path.join("dir", "file.txt")) # dir/file.txt
print(os.path.exists("test.txt")) # 文件是否存在
print(os.path.isfile("test.txt")) # 是否是文件
print(os.path.isdir("test.txt")) # 是否是目录
print(os.path.basename("/a/b/c.txt")) # c.txt
print(os.path.dirname("/a/b/c.txt")) # /a/b
print(os.path.splitext("file.txt")) # ('file', '.txt')
# 遍历目录
for root, dirs, files in os.walk("."):
for file in files:
if file.endswith(".py"):
print(os.path.join(root, file))import os
# 环境变量
print(os.environ.get("HOME", "默认值"))
print(os.environ.get("PATH"))
# 设置环境变量(仅影响当前进程)
os.environ["MY_VAR"] = "hello"
# 目录操作
print(os.getcwd()) # 当前工作目录
os.makedirs("a/b/c", exist_ok=True) # 递归创建目录
os.remove("temp.txt") # 删除文件
# 路径操作(推荐 pathlib 替代)
print(os.path.join("dir", "file.txt")) # dir/file.txt
print(os.path.exists("test.txt")) # 文件是否存在
print(os.path.isfile("test.txt")) # 是否是文件
print(os.path.isdir("test.txt")) # 是否是目录
print(os.path.basename("/a/b/c.txt")) # c.txt
print(os.path.dirname("/a/b/c.txt")) # /a/b
print(os.path.splitext("file.txt")) # ('file', '.txt')
# 遍历目录
for root, dirs, files in os.walk("."):
for file in files:
if file.endswith(".py"):
print(os.path.join(root, file))pathlib
基本操作
python
from pathlib import Path
# 创建 Path 对象
p = Path("docs/backend/Python")
home = Path.home()
cwd = Path.cwd()
# 路径拼接
data_file = Path("data") / "subdir" / "file.txt"
print(data_file) # data/subdir/file.txt
# 路径属性
print(p.name) # Python
print(p.parent) # docs/backend
print(p.parents[0]) # docs/backend
print(p.parents[1]) # docs
print(p.suffix) # ""(目录无后缀)
print(Path("test.py").suffix) # .py
print(Path("test.py").stem) # test(无后缀的文件名)
# 绝对路径 / 相对路径
print(p.absolute())
print(p.resolve()) # 解析符号链接的绝对路径from pathlib import Path
# 创建 Path 对象
p = Path("docs/backend/Python")
home = Path.home()
cwd = Path.cwd()
# 路径拼接
data_file = Path("data") / "subdir" / "file.txt"
print(data_file) # data/subdir/file.txt
# 路径属性
print(p.name) # Python
print(p.parent) # docs/backend
print(p.parents[0]) # docs/backend
print(p.parents[1]) # docs
print(p.suffix) # ""(目录无后缀)
print(Path("test.py").suffix) # .py
print(Path("test.py").stem) # test(无后缀的文件名)
# 绝对路径 / 相对路径
print(p.absolute())
print(p.resolve()) # 解析符号链接的绝对路径读写文件
python
from pathlib import Path
p = Path("example.txt")
# 写文件
p.write_text("Hello, World!", encoding="utf-8")
p.write_bytes(b"binary data")
# 读文件
content = p.read_text(encoding="utf-8")
data = p.read_bytes()
# 文件信息
print(p.exists()) # True
print(p.is_file()) # True
print(p.is_dir()) # False
print(p.stat().st_size) # 文件大小(字节)from pathlib import Path
p = Path("example.txt")
# 写文件
p.write_text("Hello, World!", encoding="utf-8")
p.write_bytes(b"binary data")
# 读文件
content = p.read_text(encoding="utf-8")
data = p.read_bytes()
# 文件信息
print(p.exists()) # True
print(p.is_file()) # True
print(p.is_dir()) # False
print(p.stat().st_size) # 文件大小(字节)遍历与匹配
python
from pathlib import Path
base = Path(".")
# 遍历目录
for child in base.iterdir():
print(child)
# 递归匹配
for py_file in base.rglob("*.py"):
print(py_file)
# 单层匹配
for md_file in base.glob("*.md"):
print(md_file)
# 目录操作
new_dir = Path("temp_dir")
new_dir.mkdir(exist_ok=True) # 创建目录
Path("temp_dir/sub").mkdir(parents=True, exist_ok=True) # 递归创建
Path("temp_dir").rmdir() # 删除空目录from pathlib import Path
base = Path(".")
# 遍历目录
for child in base.iterdir():
print(child)
# 递归匹配
for py_file in base.rglob("*.py"):
print(py_file)
# 单层匹配
for md_file in base.glob("*.md"):
print(md_file)
# 目录操作
new_dir = Path("temp_dir")
new_dir.mkdir(exist_ok=True) # 创建目录
Path("temp_dir/sub").mkdir(parents=True, exist_ok=True) # 递归创建
Path("temp_dir").rmdir() # 删除空目录路径替换与重命名
python
from pathlib import Path
p = Path("2024/report.txt")
# 替换路径部分
print(p.with_name("summary.txt")) # 2024/summary.txt
print(p.with_suffix(".md")) # 2024/report.md
print(p.with_stem("index")) # 2024/index.txt(Python 3.9+)
# 重命名文件
p = Path("old.txt")
p.write_text("test")
p.rename("new.txt") # 重命名
# p.replace("new.txt") # 覆盖式重命名from pathlib import Path
p = Path("2024/report.txt")
# 替换路径部分
print(p.with_name("summary.txt")) # 2024/summary.txt
print(p.with_suffix(".md")) # 2024/report.md
print(p.with_stem("index")) # 2024/index.txt(Python 3.9+)
# 重命名文件
p = Path("old.txt")
p.write_text("test")
p.rename("new.txt") # 重命名
# p.replace("new.txt") # 覆盖式重命名subprocess
subprocess.run
python
import subprocess
# 执行简单命令
result = subprocess.run(["echo", "Hello"], capture_output=True, text=True)
print(result.stdout) # Hello\n
print(result.returncode) # 0 表示成功
# 捕获输出
result = subprocess.run(
["python", "-c", "print('Hello from Python')"],
capture_output=True,
text=True,
)
print(result.stdout) # Hello from Python\n
# 错误处理
result = subprocess.run(
["ls", "/nonexistent"],
capture_output=True,
text=True,
)
if result.returncode != 0:
print(f"错误: {result.stderr}") # stderr 信息
# check=True — 自动抛出异常
try:
subprocess.run(["false"], check=True)
except subprocess.CalledProcessError as e:
print(f"命令失败,返回码: {e.returncode}")import subprocess
# 执行简单命令
result = subprocess.run(["echo", "Hello"], capture_output=True, text=True)
print(result.stdout) # Hello\n
print(result.returncode) # 0 表示成功
# 捕获输出
result = subprocess.run(
["python", "-c", "print('Hello from Python')"],
capture_output=True,
text=True,
)
print(result.stdout) # Hello from Python\n
# 错误处理
result = subprocess.run(
["ls", "/nonexistent"],
capture_output=True,
text=True,
)
if result.returncode != 0:
print(f"错误: {result.stderr}") # stderr 信息
# check=True — 自动抛出异常
try:
subprocess.run(["false"], check=True)
except subprocess.CalledProcessError as e:
print(f"命令失败,返回码: {e.returncode}")高级用法
python
import subprocess
# 使用 shell 模式(注意安全风险)
result = subprocess.run(
"echo hello && echo world",
shell=True,
capture_output=True,
text=True,
)
print(result.stdout)
# 管道 — 级联命令
p1 = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", ".py"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0].decode()
print(output)
# 超时控制
try:
subprocess.run(["sleep", "10"], timeout=3)
except subprocess.TimeoutExpired:
print("命令执行超时")import subprocess
# 使用 shell 模式(注意安全风险)
result = subprocess.run(
"echo hello && echo world",
shell=True,
capture_output=True,
text=True,
)
print(result.stdout)
# 管道 — 级联命令
p1 = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", ".py"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0].decode()
print(output)
# 超时控制
try:
subprocess.run(["sleep", "10"], timeout=3)
except subprocess.TimeoutExpired:
print("命令执行超时")dataclasses
基本使用
python
from dataclasses import dataclass, field
@dataclass
class Person:
name: str
age: int
email: str = "" # 默认值
tags: list = field(default_factory=list) # 可变类型需用 default_factory
# 自动生成 __init__、__repr__、__eq__ 等
p1 = Person("张三", 30, email="zhang@example.com")
p2 = Person("张三", 30, email="zhang@example.com")
print(p1) # Person(name='张三', age=30, email='zhang@example.com')
print(p1 == p2) # True(自动比较所有字段)
# 可变默认值陷阱
@dataclass
class Bad:
items: list = [] # 错误!所有实例共享同一列表
@dataclass
class Good:
items: list = field(default_factory=list) # 正确,每个实例独立from dataclasses import dataclass, field
@dataclass
class Person:
name: str
age: int
email: str = "" # 默认值
tags: list = field(default_factory=list) # 可变类型需用 default_factory
# 自动生成 __init__、__repr__、__eq__ 等
p1 = Person("张三", 30, email="zhang@example.com")
p2 = Person("张三", 30, email="zhang@example.com")
print(p1) # Person(name='张三', age=30, email='zhang@example.com')
print(p1 == p2) # True(自动比较所有字段)
# 可变默认值陷阱
@dataclass
class Bad:
items: list = [] # 错误!所有实例共享同一列表
@dataclass
class Good:
items: list = field(default_factory=list) # 正确,每个实例独立field 配置
python
from dataclasses import dataclass, field
@dataclass
class Config:
name: str
version: str = field(default="1.0", compare=False) # 不参与比较
internal_id: int = field(repr=False) # 不参与 repr
metadata: dict = field(default_factory=dict, hash=False) # 不参与哈希
# init=False — 不由 __init__ 赋值
created_at: float = field(init=False)
def __post_init__(self):
from time import time
self.created_at = time() # 构造后自动执行
c = Config("app", internal_id=42)
print(c) # 不含 internal_idfrom dataclasses import dataclass, field
@dataclass
class Config:
name: str
version: str = field(default="1.0", compare=False) # 不参与比较
internal_id: int = field(repr=False) # 不参与 repr
metadata: dict = field(default_factory=dict, hash=False) # 不参与哈希
# init=False — 不由 __init__ 赋值
created_at: float = field(init=False)
def __post_init__(self):
from time import time
self.created_at = time() # 构造后自动执行
c = Config("app", internal_id=42)
print(c) # 不含 internal_idfrozen — 不可变
python
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(1, 2)
# p.x = 3 # FrozenInstanceError: cannot assign to field 'x'
# frozen 对象可作为字典键
d = {p: "origin"}
print(d[Point(1, 2)]) # originfrom dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(1, 2)
# p.x = 3 # FrozenInstanceError: cannot assign to field 'x'
# frozen 对象可作为字典键
d = {p: "origin"}
print(d[Point(1, 2)]) # origin继承
python
from dataclasses import dataclass
@dataclass
class Base:
x: int = 0
@dataclass
class Derived(Base):
y: int = 0
d = Derived(x=1, y=2)
print(d) # Derived(x=1, y=2)from dataclasses import dataclass
@dataclass
class Base:
x: int = 0
@dataclass
class Derived(Base):
y: int = 0
d = Derived(x=1, y=2)
print(d) # Derived(x=1, y=2)hashlib / secrets
hashlib
python
import hashlib
# MD5(快速但非安全)
data = b"hello world"
md5_hash = hashlib.md5(data).hexdigest()
print(md5_hash) # 5eb63bbbe01eeed093cb22bb8f5acdc3
# SHA-256(推荐)
sha256_hash = hashlib.sha256(data).hexdigest()
print(sha256_hash) # b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
# 大文件分块哈希
def hash_file(path: str, algorithm="sha256") -> str:
h = hashlib.new(algorithm)
with open(path, "rb") as f:
while chunk := f.read(8192): # 海象运算符
h.update(chunk)
return h.hexdigest()
print(hash_file("large_file.bin"))
# 加盐哈希
password = "my_password".encode("utf-8")
salt = "random_salt".encode("utf-8")
salted_hash = hashlib.sha256(password + salt).hexdigest()import hashlib
# MD5(快速但非安全)
data = b"hello world"
md5_hash = hashlib.md5(data).hexdigest()
print(md5_hash) # 5eb63bbbe01eeed093cb22bb8f5acdc3
# SHA-256(推荐)
sha256_hash = hashlib.sha256(data).hexdigest()
print(sha256_hash) # b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
# 大文件分块哈希
def hash_file(path: str, algorithm="sha256") -> str:
h = hashlib.new(algorithm)
with open(path, "rb") as f:
while chunk := f.read(8192): # 海象运算符
h.update(chunk)
return h.hexdigest()
print(hash_file("large_file.bin"))
# 加盐哈希
password = "my_password".encode("utf-8")
salt = "random_salt".encode("utf-8")
salted_hash = hashlib.sha256(password + salt).hexdigest()secrets
python
import secrets
# 安全随机 token
token = secrets.token_hex(16) # 32 字符十六进制
print(token) # e.g. a1b2c3d4e5f6789012345678abcdef01
token_url = secrets.token_urlsafe(16) # URL 安全的 base64
print(token_url) # e.g. -abc123_xyz-
# 安全随机整数
rand = secrets.randbelow(100) # 0 <= rand < 100
print(rand)
# 从序列中安全选择
choice = secrets.choice(["a", "b", "c"])
print(choice)
# 生成密码
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = "".join(secrets.choice(alphabet) for _ in range(16))
print(password)
# 安全比较(防时序攻击)
secret = "abc123"
user_input = "abc123"
if secrets.compare_digest(secret, user_input):
print("验证通过") # 推荐用于密码/令牌比较import secrets
# 安全随机 token
token = secrets.token_hex(16) # 32 字符十六进制
print(token) # e.g. a1b2c3d4e5f6789012345678abcdef01
token_url = secrets.token_urlsafe(16) # URL 安全的 base64
print(token_url) # e.g. -abc123_xyz-
# 安全随机整数
rand = secrets.randbelow(100) # 0 <= rand < 100
print(rand)
# 从序列中安全选择
choice = secrets.choice(["a", "b", "c"])
print(choice)
# 生成密码
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = "".join(secrets.choice(alphabet) for _ in range(16))
print(password)
# 安全比较(防时序攻击)
secret = "abc123"
user_input = "abc123"
if secrets.compare_digest(secret, user_input):
print("验证通过") # 推荐用于密码/令牌比较copy
浅拷贝 vs 深拷贝
python
import copy
# 浅拷贝 — 只拷贝外层,内层引用共享
original = {"a": 1, "b": [2, 3, 4]}
shallow = copy.copy(original)
shallow["a"] = 99 # 不影响 original
print(original["a"]) # 1
shallow["b"].append(5) # 影响了 original!
print(original["b"]) # [2, 3, 4, 5]
# 深拷贝 — 递归拷贝所有内容
original = {"a": 1, "b": [2, 3, 4]}
deep = copy.deepcopy(original)
deep["b"].append(5)
print(original["b"]) # [2, 3, 4](未受影响)import copy
# 浅拷贝 — 只拷贝外层,内层引用共享
original = {"a": 1, "b": [2, 3, 4]}
shallow = copy.copy(original)
shallow["a"] = 99 # 不影响 original
print(original["a"]) # 1
shallow["b"].append(5) # 影响了 original!
print(original["b"]) # [2, 3, 4, 5]
# 深拷贝 — 递归拷贝所有内容
original = {"a": 1, "b": [2, 3, 4]}
deep = copy.deepcopy(original)
deep["b"].append(5)
print(original["b"]) # [2, 3, 4](未受影响)适用场景
python
import copy
# 列表拷贝
original_list = [[1, 2], [3, 4]]
shallow_list = copy.copy(original_list)
deep_list = copy.deepcopy(original_list)
shallow_list[0].append(99)
print(original_list) # [[1, 2, 99], [3, 4]] — 被修改了
deep_list[0].append(99)
print(original_list) # [[1, 2, 99], [3, 4]] — deep 不影响 original
# 自定义对象的拷贝
class Config:
def __init__(self):
self.data = {"key": [1, 2, 3]}
c1 = Config()
c2 = copy.deepcopy(c1)
c2.data["key"].append(4)
print(c1.data["key"]) # [1, 2, 3] — 不受影响import copy
# 列表拷贝
original_list = [[1, 2], [3, 4]]
shallow_list = copy.copy(original_list)
deep_list = copy.deepcopy(original_list)
shallow_list[0].append(99)
print(original_list) # [[1, 2, 99], [3, 4]] — 被修改了
deep_list[0].append(99)
print(original_list) # [[1, 2, 99], [3, 4]] — deep 不影响 original
# 自定义对象的拷贝
class Config:
def __init__(self):
self.data = {"key": [1, 2, 3]}
c1 = Config()
c2 = copy.deepcopy(c1)
c2.data["key"].append(4)
print(c1.data["key"]) # [1, 2, 3] — 不受影响typing(进阶补充)
TypeVar / Generic
python
from typing import TypeVar, Generic, List
T = TypeVar("T") # 类型变量
# 泛型函数
def first(items: List[T]) -> T:
return items[0]
print(first([1, 2, 3])) # 1
print(first(["a", "b"])) # a
# 泛型类
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: List[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
stack = Stack[int]()
stack.push(1)
stack.push(2)
print(stack.pop()) # 2
# 类型约束
Number = TypeVar("Number", int, float)
def add(a: Number, b: Number) -> Number:
return a + bfrom typing import TypeVar, Generic, List
T = TypeVar("T") # 类型变量
# 泛型函数
def first(items: List[T]) -> T:
return items[0]
print(first([1, 2, 3])) # 1
print(first(["a", "b"])) # a
# 泛型类
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: List[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
stack = Stack[int]()
stack.push(1)
stack.push(2)
print(stack.pop()) # 2
# 类型约束
Number = TypeVar("Number", int, float)
def add(a: Number, b: Number) -> Number:
return a + bLiteral / Final / Self
python
from typing import Literal, Final
# Literal — 限定具体值
def set_mode(mode: Literal["dev", "prod", "test"]) -> str:
return f"当前环境: {mode}"
def set_status(code: Literal[200, 201, 400, 404, 500]) -> str:
status_map = {200: "OK", 201: "Created", 400: "Bad Request",
404: "Not Found", 500: "Internal Error"}
return status_map.get(code, "Unknown")
# Final — 常量声明
VERSION: Final[str] = "2.0.0"
# VERSION = "3.0.0" # mypy 报错
# Self (Python 3.11+) — 返回自身类型
from typing import Self
class MyClass:
def copy(self) -> Self:
return type(self)()from typing import Literal, Final
# Literal — 限定具体值
def set_mode(mode: Literal["dev", "prod", "test"]) -> str:
return f"当前环境: {mode}"
def set_status(code: Literal[200, 201, 400, 404, 500]) -> str:
status_map = {200: "OK", 201: "Created", 400: "Bad Request",
404: "Not Found", 500: "Internal Error"}
return status_map.get(code, "Unknown")
# Final — 常量声明
VERSION: Final[str] = "2.0.0"
# VERSION = "3.0.0" # mypy 报错
# Self (Python 3.11+) — 返回自身类型
from typing import Self
class MyClass:
def copy(self) -> Self:
return type(self)()TypeGuard
python
from typing import TypeGuard, Union
# TypeGuard — 类型收窄
def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
return all(isinstance(x, str) for x in val)
def process(items: list[object]) -> None:
if is_str_list(items):
# 在此分支中 items 被推断为 list[str]
print(" ".join(items)) # 类型安全
else:
print("包含非字符串元素")from typing import TypeGuard, Union
# TypeGuard — 类型收窄
def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
return all(isinstance(x, str) for x in val)
def process(items: list[object]) -> None:
if is_str_list(items):
# 在此分支中 items 被推断为 list[str]
print(" ".join(items)) # 类型安全
else:
print("包含非字符串元素")overload
python
from typing import overload
# overload — 根据参数类型声明不同返回值
@overload
def parse(data: str) -> dict: ...
@overload
def parse(data: bytes) -> dict: ...
@overload
def parse(data: int) -> int: ...
def parse(data: str | bytes | int) -> dict | int:
if isinstance(data, str):
return {"type": "str", "value": data}
elif isinstance(data, bytes):
return {"type": "bytes", "value": data.decode()}
else:
return data # int 直接返回
result1 = parse("hello") # 类型检查器知道返回 dict
result2 = parse(42) # 类型检查器知道返回 intfrom typing import overload
# overload — 根据参数类型声明不同返回值
@overload
def parse(data: str) -> dict: ...
@overload
def parse(data: bytes) -> dict: ...
@overload
def parse(data: int) -> int: ...
def parse(data: str | bytes | int) -> dict | int:
if isinstance(data, str):
return {"type": "str", "value": data}
elif isinstance(data, bytes):
return {"type": "bytes", "value": data.decode()}
else:
return data # int 直接返回
result1 = parse("hello") # 类型检查器知道返回 dict
result2 = parse(42) # 类型检查器知道返回 intProtocol vs ABC
python
from typing import Protocol
from abc import ABC, abstractmethod
# Protocol — 结构性子类型(鸭子类型)
class Drawable(Protocol):
def draw(self) -> str: ...
class Circle:
def draw(self) -> str:
return "○"
def render(obj: Drawable) -> None:
print(obj.draw())
render(Circle()) # 无需继承,满足结构即可
# ABC — 名义子类型(需显式继承)
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
class Square(Shape):
def __init__(self, side: float):
self.side = side
def area(self) -> float:
return self.side ** 2
# s: Shape = Circle() # 错误!Circle 未继承 Shapefrom typing import Protocol
from abc import ABC, abstractmethod
# Protocol — 结构性子类型(鸭子类型)
class Drawable(Protocol):
def draw(self) -> str: ...
class Circle:
def draw(self) -> str:
return "○"
def render(obj: Drawable) -> None:
print(obj.draw())
render(Circle()) # 无需继承,满足结构即可
# ABC — 名义子类型(需显式继承)
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
class Square(Shape):
def __init__(self, side: float):
self.side = side
def area(self) -> float:
return self.side ** 2
# s: Shape = Circle() # 错误!Circle 未继承 Shapeenum
基本枚举
python
from enum import Enum, IntEnum, auto, unique
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# 访问
print(Color.RED) # Color.RED
print(Color.RED.name) # RED
print(Color.RED.value) # 1
# 遍历
for c in Color:
print(c.name, c.value)
# 通过值查找
print(Color(2)) # Color.GREEN
# 通过名称查找
print(Color["BLUE"]) # Color.BLUEfrom enum import Enum, IntEnum, auto, unique
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# 访问
print(Color.RED) # Color.RED
print(Color.RED.name) # RED
print(Color.RED.value) # 1
# 遍历
for c in Color:
print(c.name, c.value)
# 通过值查找
print(Color(2)) # Color.GREEN
# 通过名称查找
print(Color["BLUE"]) # Color.BLUEauto — 自动赋值
python
from enum import Enum, auto
class Status(Enum):
PENDING = auto() # 1
PROCESSING = auto() # 2
SUCCESS = auto() # 3
FAILED = auto() # 4
for s in Status:
print(s.name, s.value) # PENDING 1, PROCESSING 2, ...
# 自定义 auto 起始值
class CustomBase(Enum):
def _generate_next_value_(name, start, count, last_values):
return count * 10
class Priority(CustomBase):
LOW = auto() # 0
MEDIUM = auto() # 10
HIGH = auto() # 20from enum import Enum, auto
class Status(Enum):
PENDING = auto() # 1
PROCESSING = auto() # 2
SUCCESS = auto() # 3
FAILED = auto() # 4
for s in Status:
print(s.name, s.value) # PENDING 1, PROCESSING 2, ...
# 自定义 auto 起始值
class CustomBase(Enum):
def _generate_next_value_(name, start, count, last_values):
return count * 10
class Priority(CustomBase):
LOW = auto() # 0
MEDIUM = auto() # 10
HIGH = auto() # 20unique — 值唯一
python
from enum import Enum, unique
@unique
class ErrorCode(Enum):
OK = 0
NOT_FOUND = 404
SERVER_ERROR = 500
# DUPLICATE = 404 # ValueError: duplicate values foundfrom enum import Enum, unique
@unique
class ErrorCode(Enum):
OK = 0
NOT_FOUND = 404
SERVER_ERROR = 500
# DUPLICATE = 404 # ValueError: duplicate values foundIntEnum
python
from enum import IntEnum
# IntEnum — 可与整数比较
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
print(Priority.HIGH > Priority.MEDIUM) # True
print(Priority.LOW == 1) # True(IntEnum 特有)
print(Priority.LOW < 3) # True
# 可用作字典键
task_count = {Priority.HIGH: 5, Priority.LOW: 10}from enum import IntEnum
# IntEnum — 可与整数比较
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
print(Priority.HIGH > Priority.MEDIUM) # True
print(Priority.LOW == 1) # True(IntEnum 特有)
print(Priority.LOW < 3) # True
# 可用作字典键
task_count = {Priority.HIGH: 5, Priority.LOW: 10}标志位 (Flag)
python
from enum import Flag, auto
class Permission(Flag):
NONE = 0
READ = auto() # 1
WRITE = auto() # 2
EXECUTE = auto() # 4
ALL = READ | WRITE | EXECUTE
perm = Permission.READ | Permission.WRITE
print(perm) # Permission.READ|WRITE
print(Permission.READ in perm) # True
print(Permission.EXECUTE in perm) # False
# 权限检查
if perm & Permission.READ:
print("有读权限")from enum import Flag, auto
class Permission(Flag):
NONE = 0
READ = auto() # 1
WRITE = auto() # 2
EXECUTE = auto() # 4
ALL = READ | WRITE | EXECUTE
perm = Permission.READ | Permission.WRITE
print(perm) # Permission.READ|WRITE
print(Permission.READ in perm) # True
print(Permission.EXECUTE in perm) # False
# 权限检查
if perm & Permission.READ:
print("有读权限")random / math
random
python
import random
# 随机选择
items = ["苹果", "香蕉", "橘子", "葡萄"]
print(random.choice(items)) # 随机选一个
print(random.choices(items, k=2)) # 有放回选 k 个
print(random.sample(items, k=2)) # 无放回选 k 个
# 随机整数
print(random.randint(1, 10)) # 包含两端 [1, 10]
print(random.randrange(0, 10, 2)) # [0, 10) 步长 2
# 随机浮点数
print(random.random()) # [0.0, 1.0)
print(random.uniform(1, 10)) # [1.0, 10.0]
# 打乱顺序
cards = list(range(52))
random.shuffle(cards) # 原地打乱
print(cards[:5])
# 设置种子(可复现)
random.seed(42)
print(random.randint(1, 100)) # 每次运行结果一致
# 加权随机
choices = ["普通", "稀有", "传说"]
weights = [70, 25, 5]
print(random.choices(choices, weights=weights, k=10))import random
# 随机选择
items = ["苹果", "香蕉", "橘子", "葡萄"]
print(random.choice(items)) # 随机选一个
print(random.choices(items, k=2)) # 有放回选 k 个
print(random.sample(items, k=2)) # 无放回选 k 个
# 随机整数
print(random.randint(1, 10)) # 包含两端 [1, 10]
print(random.randrange(0, 10, 2)) # [0, 10) 步长 2
# 随机浮点数
print(random.random()) # [0.0, 1.0)
print(random.uniform(1, 10)) # [1.0, 10.0]
# 打乱顺序
cards = list(range(52))
random.shuffle(cards) # 原地打乱
print(cards[:5])
# 设置种子(可复现)
random.seed(42)
print(random.randint(1, 100)) # 每次运行结果一致
# 加权随机
choices = ["普通", "稀有", "传说"]
weights = [70, 25, 5]
print(random.choices(choices, weights=weights, k=10))math
python
import math
# 数学常量
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
print(math.inf) # inf
print(math.nan) # nan
# 取整
print(math.floor(3.7)) # 3(向下取整)
print(math.ceil(3.2)) # 4(向上取整)
print(math.trunc(3.7)) # 3(截断)
print(round(3.5)) # 4(Python 内置,银行家舍入)
print(round(4.5)) # 4
# 平方/根
print(math.sqrt(16)) # 4.0
print(math.pow(2, 10)) # 1024.0
print(math.isclose(0.1 + 0.2, 0.3)) # True(安全浮点比较)
# 三角函数
print(math.sin(math.pi / 2)) # 1.0
print(math.cos(0)) # 1.0
print(math.radians(180)) # 3.14159...(角度转弧度)
print(math.degrees(math.pi)) # 180.0(弧度转角度)
# 对数
print(math.log(100, 10)) # 2.0(以 10 为底)
print(math.log(math.e)) # 1.0(自然对数)
print(math.log2(8)) # 3.0
print(math.log10(1000)) # 3.0
# 最大公约数 / 最小公倍数 (Python 3.9+)
print(math.gcd(12, 18)) # 6
print(math.lcm(4, 6)) # 12
# 组合数 / 排列数
print(math.comb(5, 2)) # 10(C(5,2))
print(math.perm(5, 2)) # 20(P(5,2))
# 阶乘
print(math.factorial(5)) # 120import math
# 数学常量
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
print(math.inf) # inf
print(math.nan) # nan
# 取整
print(math.floor(3.7)) # 3(向下取整)
print(math.ceil(3.2)) # 4(向上取整)
print(math.trunc(3.7)) # 3(截断)
print(round(3.5)) # 4(Python 内置,银行家舍入)
print(round(4.5)) # 4
# 平方/根
print(math.sqrt(16)) # 4.0
print(math.pow(2, 10)) # 1024.0
print(math.isclose(0.1 + 0.2, 0.3)) # True(安全浮点比较)
# 三角函数
print(math.sin(math.pi / 2)) # 1.0
print(math.cos(0)) # 1.0
print(math.radians(180)) # 3.14159...(角度转弧度)
print(math.degrees(math.pi)) # 180.0(弧度转角度)
# 对数
print(math.log(100, 10)) # 2.0(以 10 为底)
print(math.log(math.e)) # 1.0(自然对数)
print(math.log2(8)) # 3.0
print(math.log10(1000)) # 3.0
# 最大公约数 / 最小公倍数 (Python 3.9+)
print(math.gcd(12, 18)) # 6
print(math.lcm(4, 6)) # 12
# 组合数 / 排列数
print(math.comb(5, 2)) # 10(C(5,2))
print(math.perm(5, 2)) # 20(P(5,2))
# 阶乘
print(math.factorial(5)) # 120总结
| 模块 | 主要用途 | 日常频率 |
|---|---|---|
re | 正则匹配与替换 | ★★★★★ |
datetime | 日期时间处理 | ★★★★★ |
json | JSON 序列化/反序列化 | ★★★★★ |
pathlib | 文件路径操作(替代 os.path) | ★★★★★ |
logging | 日志记录 | ★★★★ |
collections | 增强数据结构 | ★★★★ |
subprocess | 执行外部命令 | ★★★ |
argparse | 命令行参数解析 | ★★★ |
hashlib | 哈希计算 | ★★★ |
dataclasses | 数据类定义 | ★★★ |
enum | 枚举类型 | ★★★ |
random | 随机数 | ★★★ |
copy | 深/浅拷贝 | ★★ |
typing | 类型注解 | ★★ |
secrets | 安全随机 | ★★ |
os | 系统接口 | ★★ |
sys | Python 运行时 | ★★ |
csv | CSV 文件读写 | ★★ |
math | 数学计算 | ★★ |
time | 时间/休眠 | ★★ |
calendar | 日历处理 | ★ |
Cao Note