Skip to content

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.com
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.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")))  # True
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")))  # 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:00
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: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"])  # False
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"])  # False

logging ​

基本配置 ​

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_id
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_id

frozen — 不可变 ​

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)])  # origin
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)])  # 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 + b
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 + b

Literal / 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)       # 类型检查器知道返回 int
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)       # 类型检查器知道返回 int

Protocol 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 未继承 Shape
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 未继承 Shape

enum ​

基本枚举 ​

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.BLUE
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.BLUE

auto — 自动赋值 ​

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()      # 20
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()      # 20

unique — 值唯一 ​

python
from enum import Enum, unique

@unique
class ErrorCode(Enum):
    OK = 0
    NOT_FOUND = 404
    SERVER_ERROR = 500
    # DUPLICATE = 404  # ValueError: duplicate values found
from enum import Enum, unique

@unique
class ErrorCode(Enum):
    OK = 0
    NOT_FOUND = 404
    SERVER_ERROR = 500
    # DUPLICATE = 404  # ValueError: duplicate values found

IntEnum ​

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))   # 120
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))   # 120

总结 ​

模块主要用途日常频率
re正则匹配与替换★★★★★
datetime日期时间处理★★★★★
jsonJSON 序列化/反序列化★★★★★
pathlib文件路径操作(替代 os.path)★★★★★
logging日志记录★★★★
collections增强数据结构★★★★
subprocess执行外部命令★★★
argparse命令行参数解析★★★
hashlib哈希计算★★★
dataclasses数据类定义★★★
enum枚举类型★★★
random随机数★★★
copy深/浅拷贝★★
typing类型注解★★
secrets安全随机★★
os系统接口★★
sysPython 运行时★★
csvCSV 文件读写★★
math数学计算★★
time时间/休眠★★
calendar日历处理★