Python(三十八) 常用内置模块详解教程
目录
一、os 模块:操作系统接口
1.0 模块定位
os 模块是你和操作系统之间的翻译官。你想让操作系统帮你"创建一个文件夹"、"删除一个文件"、"看看当前目录有什么",不用自己写底层指令,通过 os 模块就能完成。
生活类比:操作系统就像一个国家的政府,你想办个手续(比如查户口、建房审批),不需要直接跑到市长办公室,而是去政务大厅(os 模块),工作人员帮你代办。
import os # 导入模块,所有功能都在 os.xxx 里
1.1 文件和目录的增删改查
创建目录
import os
# 创建单个目录(父目录必须存在,否则报错)
os.mkdir("my_folder")
print("文件夹已创建")
# 递归创建多层目录(父目录不存会自动创建,推荐!)
os.makedirs("project/src/utils", exist_ok=True)
# exist_ok=True:如果目录已经存在,不报错,直接跳过
print("多层目录已创建")
删除文件和目录
import os
# 删除文件(文件不存在会报错,建议先判断)
if os.path.exists("temp.txt"):
os.remove("temp.txt")
print("文件已删除")
else:
print("文件不存在,无需删除")
# 删除空目录
os.rmdir("empty_folder") # 注意:只能删空目录!
# 删除非空目录需要用 shutil 模块
# import shutil
# shutil.rmtree("non_empty_folder")
重命名
import os
# 重命名文件或目录
os.rename("old_name.txt", "new_name.txt")
print("重命名完成")
查看目录内容
import os
# 列出当前目录的所有文件和文件夹(只返回名字)
items = os.listdir(".")
print("当前目录内容:")
for item in items:
print(f" - {item}")
# 递归遍历目录树(子子孙孙全部列出来)
print("\n完整目录树:")
for root, dirs, files in os.walk("."):
# root: 当前正在看的目录路径
# dirs: 当前目录下的所有子目录
# files: 当前目录下的所有文件
depth = root.count(os.sep) # 用分隔符数量表示层级深度
indent = " " * depth
print(f"{indent}[目录] {root}")
for file in files:
print(f"{indent} 📄 {file}")
新手易踩坑:
- 坑 1:
os.mkdir("a/b")其中a不存在 → 报错!请用os.makedirs("a/b")- 坑 2:
os.rmdir()删非空目录 → 报错!非空目录用shutil.rmtree()- 坑 3:
os.listdir()返回的只是名字,不是完整路径 → 拼完整路径用os.path.join()
1.2 路径处理
import os
# === 拼接路径(自动处理 / 和 \ 的问题)===
# 不要: "folder" + "\\" + "file.txt"
# 应该:
path = os.path.join("folder", "subfolder", "file.txt")
print(f"拼接结果:{path}")
# Windows 输出:folder\subfolder\file.txt
# Linux 输出: folder/subfolder/file.txt
# === 路径拆分 ===
path = "/home/user/documents/report.pdf"
# 获取目录部分和文件名
print(os.path.dirname(path)) # /home/user/documents
print(os.path.basename(path)) # report.pdf
# 分离文件名和后缀
name, ext = os.path.splitext("report.pdf")
print(f"主名:{name},后缀:{ext}") # 主名:report,后缀:.pdf
# === 路径判断 ===
target = "data.txt"
print(f"是否存在:{os.path.exists(target)}")
print(f"是文件吗:{os.path.isfile(target)}")
print(f"是目录吗:{os.path.isdir(target)}")
print(f"是绝对路径吗:{os.path.isabs(target)}")
# === 获取绝对路径 ===
cwd = os.getcwd() # 当前工作目录
abs_path = os.path.abspath(".") # 相对路径转绝对路径
print(f"当前工作目录:{cwd}")
print(f"绝对路径:{abs_path}")
跨平台路径的易错点:
# 错误写法(不跨平台):
# file_path = "data\images\photo.jpg" # Windows 上 \i 会被当成转义符!
# 正确写法1:用 os.path.join
file_path = os.path.join("data", "images", "photo.jpg")
# 正确写法2:用原始字符串
file_path = r"data\images\photo.jpg" # r 前缀让 \ 变成普通字符
# 正确写法3:直接用 /(Python 在 Windows 上也能识别)
file_path = "data/images/photo.jpg"
1.3 系统信息与文件属性
import os
# 系统信息
print(f"操作系统名称:{os.name}") # nt=Windows, posix=Linux/macOS
print(f"当前工作目录:{os.getcwd()}")
print(f"登录用户名:{os.getlogin()}")
# 环境变量
print(f"PATH 环境变量:{os.environ.get('PATH', '未设置')}")
# 文件属性
if os.path.exists("test.txt"):
stat = os.stat("test.txt")
print(f"文件大小:{stat.st_size} 字节")
print(f"最后修改时间:{stat.st_mtime}")
print(f"创建时间:{stat.st_ctime}")
1.4 执行系统命令
import os
# 执行一条系统命令并返回退出码
# ret = os.system("dir") # Windows 上列出目录
# ret = os.system("ls -la") # Linux/macOS 上
# 执行命令并读取输出(推荐)
# result = os.popen("dir").read()
# print(result)
课堂练习题 — os 模块
练习 1:在当前目录下创建 school/class1/students 三层目录,然后列出 school 目录下的所有内容。
练习 2:写一个函数 safe_delete(filepath),如果文件存在则删除并打印"已删除",否则打印"文件不存在"。
练习 3:用 os.walk() 遍历当前目录,统计一共有多少个 .py 文件。
练习 4:获取当前文件的绝对路径,分离出目录部分和文件名部分。
二、sys 模块:系统运行时信息
2.0 模块定位
sys 模块管理的是Python 解释器本身的运行时信息。如果说 os 是"和操作系统对话",那 sys 就是"和 Python 解释器对话"。它帮你获取命令行参数、控制程序退出、查看模块搜索路径等。
生活类比:sys 就像汽车的仪表盘——它不参与行驶(不处理业务逻辑),但告诉你车速多少(运行状态)、还剩多少油(内存使用)、行驶了多远(命令行参数)。
import sys
2.1 命令行参数:sys.argv
sys.argv 是程序从命令行收到的参数列表。argv[0] 永远是脚本名本身,后面的才是真正的参数。
# 文件名:greet.py
import sys
print(f"脚本名:{sys.argv[0]}")
print(f"所有参数:{sys.argv}")
if len(sys.argv) > 1:
name = sys.argv[1]
print(f"你好,{name}!")
else:
print("用法:python greet.py <你的名字>")
# 命令行运行:
# > python greet.py 小明 18
# 脚本名:greet.py
# 所有参数:['greet.py', '小明', '18']
# 你好,小明!
实战案例:一个简易命令行计算器
# 文件名:calc.py
import sys
if len(sys.argv) != 4:
print("用法:python calc.py <数字1> <运算符> <数字2>")
print("示例:python calc.py 10 + 5")
sys.exit(1) # 参数不对,退出程序
num1 = float(sys.argv[1])
operator = sys.argv[2]
num2 = float(sys.argv[3])
if operator == "+":
result = num1 + num2
elif operator == "-":
result = num1 - num2
elif operator == "*":
result = num1 * num2
elif operator == "/":
result = num1 / num2 if num2 != 0 else "错误:除数不能为零"
else:
result = f"错误:不支持的运算符 '{operator}'"
print(f"{num1} {operator} {num2} = {result}")
# 命令行运行:
# > python calc.py 10 + 5
# 10.0 + 5.0 = 15.0
2.2 程序退出:sys.exit()
import sys
def check_age(age):
if age < 0:
print("错误:年龄不能为负数!")
sys.exit(1) # 退出码非 0 表示异常退出
elif age < 18:
print("未满 18 岁,无法继续")
sys.exit(0) # 退出码 0 表示正常退出
else:
print("欢迎!")
check_age(15) # 输出"未满 18 岁,无法继续"后程序终止
# check_age(15) 后面的代码都不会执行
退出码约定:0 = 正常退出,1(或其他非零值)= 异常退出。这在 Linux 脚本中很重要。
2.3 模块搜索路径:sys.path
sys.path 是一个列表,Python 按顺序去这些路径里找你要导入的模块。
import sys
print("当前模块搜索路径:")
for i, path in enumerate(sys.path, 1):
print(f" {i}. {path}")
实战场景:动态添加模块搜索路径
import sys
# 场景:你的项目结构是这样:
# my_project/
# ├── main.py ← 你在这里
# └── libs/
# └── my_utils.py ← 你想导入这个
# 方法:把 libs 目录加到 sys.path 中
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "libs"))
# 现在可以导入了
# import my_utils
2.4 标准输入/输出/错误流
import sys
# stdout:标准输出(print 实际上就写到这里)
sys.stdout.write("这行等价于 print,但没有自动换行\n")
# stderr:标准错误输出(错误信息写到这里,可以独立重定向)
sys.stderr.write("这是一条错误信息\n")
# stdin:标准输入(input 实际上就从这里读)
print("请输入一行文字:")
line = sys.stdin.readline().strip()
# 等价于 line = input()
print(f"你输入了:{line}")
实战:错误信息和正常输出分离
import sys
# 场景:程序运行时,正常结果输出到 result.txt,错误信息显示在屏幕上
# (命令行重定向前提)
for i in range(5):
if i % 2 == 0:
sys.stdout.write(f"处理第 {i} 项...成功\n")
else:
sys.stderr.write(f"处理第 {i} 项...失败\n")
# 命令行运行:
# > python script.py > result.txt
# 正常输出进了 result.txt,错误信息仍然显示在屏幕上!
2.5 其他常用属性
import sys
print(f"Python 版本:{sys.version}")
print(f"Python 版本号:{sys.version_info}") # sys.version_info(major=3, minor=11, ...)
print(f"操作系统平台:{sys.platform}") # win32 / linux / darwin
# 检查 Python 版本(大版本必须是 3)
if sys.version_info.major < 3:
print("请使用 Python 3!")
sys.exit(1)
# 递归深度限制
print(f"最大递归深度:{sys.getrecursionlimit()}")
# 已加载的模块
print(f"已加载模块数量:{len(sys.modules)}")
课堂练习题 — sys 模块
练习 1:写一个脚本 add.py,从命令行接收两个数字,输出它们的和。如果参数不足则提示用法并退出。
练习 2:用 sys.stdout.write() 输出五行数字(每行一个),再用 sys.stderr.write() 输出两行警告。
练习 3:打印当前 Python 版本信息,如果是 Python 3.8 以下版本则输出警告。
三、math 模块:数学运算
3.0 模块定位
math 模块提供了高级数学函数和常量。Python 自带 +、-、*、/ 等基础运算符,但要做开方、三角函数、对数运算,就需要 math 了。
生活类比:+、-、*、/ 就像加减法口算——日常够用。而 math 就像科学计算器——有 sin、cos、log、√ 等高级按钮。
import math
3.1 数学常量
import math
print(f"π(圆周率):{math.pi}") # 3.141592653589793
print(f"e(自然常数):{math.e}") # 2.718281828459045
print(f"τ(2π,一圈的弧度):{math.tau}") # 6.283185307179586
print(f"无穷大:{math.inf}") # inf
print(f"非数字:{math.nan}") # nan
# 实用示例:计算圆的面积
radius = 5
area = math.pi * radius ** 2
print(f"半径为 {radius} 的圆面积:{area:.2f}") # 78.54
# 判断一个数是否为无穷大
big = float("inf")
print(f"是无穷大吗:{math.isinf(big)}") # True
3.2 数值运算函数
import math
# === 取整操作 ===
print(f"向上取整 ceil(3.2):{math.ceil(3.2)}") # 4
print(f"向上取整 ceil(-3.2):{math.ceil(-3.2)}") # -3
print(f"向下取整 floor(3.8):{math.floor(3.8)}") # 3
print(f"向下取整 floor(-3.8):{math.floor(-3.8)}") # -4
print(f"截断取整 trunc(3.8):{math.trunc(3.8)}") # 3(直接砍掉小数)
# 注意:math.floor 向负无穷取整,math.trunc 向零取整
# floor(-3.2) = -4 (更小)
# trunc(-3.2) = -3 (更接近零)
# === 绝对值与符号 ===
print(f"绝对值 fabs(-5.5):{math.fabs(-5.5)}") # 5.5
print(f"复制符号 copysign(1, -3):{math.copysign(1, -3)}") # -1.0
# === 幂运算与开方 ===
print(f"平方根 sqrt(16):{math.sqrt(16)}") # 4.0
print(f"幂 pow(2, 3):{math.pow(2, 3)}") # 8.0(和 2**3 一样,但返回浮点数)
print(f"e 的幂 exp(1):{math.exp(1)}") # 2.71828... 即 e¹
# === 阶乘与组合 ===
print(f"阶乘 factorial(5):{math.factorial(5)}") # 120 (5×4×3×2×1)
print(f"组合 comb(5,2):{math.comb(5, 2)}") # 10 (5选2的组合数)
print(f"排列 perm(5,2):{math.perm(5, 2)}") # 20 (5选2的排列数)
# === 最大公约数和余数 ===
print(f"最大公约数 gcd(12, 18):{math.gcd(12, 18)}") # 6
print(f"最小公倍数 lcm(12, 18):{math.lcm(12, 18)}") # 36
print(f"带余除法 divmod(10, 3):{divmod(10, 3)}") # (3, 1) 商3余1
3.3 三角函数
import math
# 角度转弧度(三角函数需要弧度!)
angle_deg = 30
angle_rad = math.radians(angle_deg) # 30° → 0.5236 弧度
# 反过来:math.degrees(rad) 弧度转角度
# 三角函数(传入的是弧度)
print(f"sin(30°) = {math.sin(angle_rad):.4f}") # 0.5000
print(f"cos(60°) = {math.cos(math.radians(60)):.4f}") # 0.5000
print(f"tan(45°) = {math.tan(math.radians(45)):.4f}") # 1.0000
# 反三角函数(返回值是弧度)
print(f"arcsin(0.5) = {math.degrees(math.asin(0.5)):.1f}°") # 30.0°
print(f"arctan(1) = {math.degrees(math.atan(1)):.1f}°") # 45.0°
# 直角坐标转极坐标
x, y = 3, 4
r = math.hypot(x, y) # 距离 = √(x²+y²) = 5.0
theta = math.atan2(y, x) # 角度(弧度)
print(f"极坐标:距离={r},角度={math.degrees(theta):.1f}°")
3.4 对数函数
import math
# 自然对数(以 e 为底)
print(f"ln(e) = {math.log(math.e):.1f}") # 1.0
print(f"ln(10) = {math.log(10):.4f}") # 2.3026
# 以 10 为底
print(f"log₁₀(100) = {math.log10(100):.1f}") # 2.0
# 以 2 为底
print(f"log₂(8) = {math.log2(8):.1f}") # 3.0
# 以任意数为底(以 3 为底求 log₃27)
print(f"log₃(27) = {math.log(27, 3):.1f}") # 3.0
3.5 math 与 Python 原生运算符的区别
import math
# 1. 整数除法 vs 浮点开方
print(16 ** 0.5) # 4.0 (Python 运算符)
print(math.sqrt(16)) # 4.0 (math 函数 —— 专门做开方,意图更明确)
# 2. 整数幂 vs 浮点幂
print(2 ** 3) # 8 (int —— 结果取决于输入类型)
print(math.pow(2, 3)) # 8.0 (float —— 始终返回浮点数)
# 3. 绝对值:内置 abs() vs math.fabs()
print(abs(-5)) # 5 (int —— 返回同类型)
print(math.fabs(-5)) # 5.0 (float —— 始终返回浮点数)
# 4. math 有特殊的数值处理
print(math.isclose(0.1 + 0.2, 0.3)) # True
# 0.1 + 0.2 在浮点数中不是精确的 0.3,但 isclose 判断足够接近
print(0.1 + 0.2 == 0.3) # False —— 直接比较会出问题!
课堂练习题 — math 模块
练习 1:输入一个圆的半径,计算并输出它的面积和周长。
练习 2:使用 math.comb() 计算从 52 张牌中任意抽 5 张有几种可能。
练习 3:计算 sin(45°)、cos(45°)、tan(45°) 的值。
练习 4:一个人距离一座大楼 50 米,仰角 30°,求大楼高度。(提示:高度 = 距离 × tan(仰角))
练习 5:用 math.isclose() 判断 0.1 × 3 是否等于 0.3?
四、datetime 模块:日期时间处理
4.0 模块定位
datetime 是 Python 中处理日期和时间的主力模块。它能创建日期对象、格式化输出、计算两个日期之间的差值,是日常开发中最常用的时间模块。
生活类比:datetime 就是你的电子日历——能看今天是几号、下个月几号是周几、距离过年还有多少天。
from datetime import datetime, date, time, timedelta
# 注意:模块叫 datetime,里面有个类也叫 datetime(容易搞混!)
4.1 四大核心类
| 类 | 表示什么 | 示例 |
|---|---|---|
date |
日期(年、月、日) | 2026-07-01 |
time |
时间(时、分、秒、微秒) | 14:30:00 |
datetime |
日期 + 时间 | 2026-07-01 14:30:00 |
timedelta |
时间差(两个时间之间的间隔) | 3天5小时 |
4.2 创建日期时间对象
from datetime import datetime, date, time
# === 获取当前日期时间 ===
now = datetime.now() # 当前日期+时间
today = date.today() # 仅当前日期
print(f"现在:{now}") # 2026-07-01 14:30:00.123456
print(f"今天:{today}") # 2026-07-01
# === 手动创建 ===
d = date(2026, 7, 1) # 年, 月, 日
t = time(14, 30, 0) # 时, 分, 秒
dt = datetime(2026, 7, 1, 14, 30, 0) # 年, 月, 日, 时, 分, 秒
dt2 = datetime(2026, 7, 1, 14, 30, 0, 500) # 最后是微秒
print(f"日期:{d}") # 2026-07-01
print(f"时间:{t}") # 14:30:00
print(f"日期时间:{dt}") # 2026-07-01 14:30:00
# === 获取时间的各个部分 ===
print(f"年:{now.year}")
print(f"月:{now.month}")
print(f"日:{now.day}")
print(f"时:{now.hour}")
print(f"分:{now.minute}")
print(f"秒:{now.second}")
print(f"微秒:{now.microsecond}")
print(f"星期几(0=周一,6=周日):{now.weekday()}")
print(f"星期几(1=周日,7=周六):{now.isoweekday()}")
4.3 日期时间的格式化输出
strftime = string format time —— 把日期时间对象变成字符串。
from datetime import datetime
now = datetime.now()
# 格式代码速查表
# %Y = 四位年份(2026) %y = 两位年份(26)
# %m = 月份(07) %d = 日(01)
# %H = 24小时制(14) %I = 12小时制(02)
# %M = 分钟(30) %S = 秒(00)
# %p = AM/PM
# %A = 完整星期名 %a = 缩写星期名
# %B = 完整月份名 %b = 缩写月份名
# 常用格式
print(now.strftime("%Y-%m-%d")) # 2026-07-01
print(now.strftime("%Y年%m月%d日")) # 2026年07月01日
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-07-01 14:30:00
print(now.strftime("%A, %B %d, %Y")) # Wednesday, July 01, 2026
print(now.strftime("%Y/%m/%d %I:%M %p")) # 2026/07/01 02:30 PM
4.4 字符串转日期时间
strptime = string parse time —— 把字符串解析成日期时间对象。
from datetime import datetime
# 字符串 → datetime
s1 = "2026-07-01"
dt1 = datetime.strptime(s1, "%Y-%m-%d")
print(f"解析结果:{dt1},类型:{type(dt1)}")
# 解析结果:2026-07-01 00:00:00,类型:<class 'datetime.datetime'>
s2 = "2026年07月01日 14时30分"
dt2 = datetime.strptime(s2, "%Y年%m月%d日 %H时%M分")
print(f"解析结果:{dt2}")
s3 = "01/07/2026 14:30:00"
dt3 = datetime.strptime(s3, "%d/%m/%Y %H:%M:%S")
print(f"解析结果:{dt3}")
# 关键规则:字符串格式和格式字符串必须完全匹配!
# "2026-07-01" 配 "%Y-%m-%d" √
# "2026/07/01" 配 "%Y-%m-%d" ✗(分隔符不匹配!)
新手易踩坑:
- 坑:
strftimevsstrptime傻傻分不清 →strftime= 格式化输出(f = format),strptime= 解析输入(p = parse)- 记忆口诀:f = 输出(format out),p = 输入(parse in)
4.5 timedelta:日期时间的加减
timedelta 表示一段时间间隔,可以和 date、datetime 做加减运算。
from datetime import datetime, date, timedelta
# === 创建时间间隔 ===
one_day = timedelta(days=1)
three_days = timedelta(days=3)
one_week = timedelta(weeks=1)
one_hour = timedelta(hours=1)
thirty_minutes = timedelta(minutes=30)
# 复杂间隔
gap = timedelta(days=2, hours=5, minutes=30)
# 表示 2天5小时30分钟
# === 日期加减 ===
today = date.today()
print(f"今天:{today}")
print(f"明天:{today + timedelta(days=1)}")
print(f"昨天:{today - timedelta(days=1)}")
print(f"一周后:{today + one_week}")
print(f"三天前:{today - three_days}")
# === datetime 加减 ===
now = datetime.now()
print(f"现在:{now}")
print(f"一小时前:{now - timedelta(hours=1)}")
print(f"两小时三十分钟后:{now + timedelta(hours=2, minutes=30)}")
# === 计算两个日期之间的天数 ===
birthday = date(2005, 8, 15)
today = date.today()
age_days = (today - birthday).days
print(f"从 {birthday} 到 {today} 过了 {age_days} 天")
# (today - birthday) 返回一个 timedelta 对象,用 .days 取其中的天数
print(f"大约 {age_days // 365} 岁") # 整数除法,粗略估算
4.6 日期比较
from datetime import date
d1 = date(2026, 7, 1)
d2 = date(2026, 12, 25)
d3 = date(2026, 7, 1)
print(d1 < d2) # True(7月1日早于12月25日)
print(d1 == d3) # True(同一天)
print(d1 != d2) # True
print(d1 >= d2) # False
# 判断一个日期是否在某个区间内
if date(2026, 9, 1) >= d1 and date(2026, 9, 1) <= d2:
print("9月1日在暑假和圣诞节之间")
4.7 实用案例:计算年龄和倒计时
from datetime import date, datetime
# === 案例1:计算精确年龄 ===
def calculate_age(birth_date):
"""根据出生日期计算精确年龄"""
today = date.today()
# 先按年份差计算
age = today.year - birth_date.year
# 如果今年的生日还没到,减一岁
if today.month < birth_date.month or \
(today.month == birth_date.month and today.day < birth_date.day):
age -= 1
return age
print(f"年龄:{calculate_age(date(2005, 8, 15))} 岁")
# === 案例2:考试倒计时 ===
exam_date = date(2026, 12, 20)
today = date.today()
remaining = (exam_date - today).days
print(f"距离期末还有 {remaining} 天")
if remaining <= 0:
print("考试已经过了!")
elif remaining <= 7:
print("只剩不到一周了,抓紧复习!")
elif remaining <= 30:
print("还有一个月,按计划复习")
else:
print("时间还充裕,但也别太放松")
# === 案例3:计算本月有多少天 ===
# 下个月的第1天减去1天 = 本月最后一天
import calendar
days_in_month = calendar.monthrange(today.year, today.month)[1]
print(f"本月有 {days_in_month} 天")
课堂练习题 — datetime 模块
练习 1:获取当前日期时间,用三种格式输出。(如 2026-07-01、2026年7月1日、July 01, 2026)
练习 2:写一个函数,输入出生日期(字符串如 "2005-08-15"),返回精确年龄。
练习 3:计算距离 2027 年元旦还有多少天。
练习 4:将 "2026/10/01 10:30:00" 解析成 datetime 对象,然后加 3 天 5 小时。
练习 5:判断今天是否为周末。
五、time 模块:时间相关操作
5.0 模块定位
time 模块处理的是底层时间:时间戳(秒数)、休眠、性能计时等。它与 datetime 分工不同——datetime 处理"人类可读的日历时间",time 处理"计算机底层的时间值"。
生活类比:
time= 秒表(精确到毫秒微秒,看事情花了多久)datetime= 台历(看今天是几号、下个月几号放假)
import time
5.1 时间戳:计算机眼中的时间
时间戳是指从1970年1月1日 00:00:00(UTC) 到现在经过的秒数。所有计算机都用同一个起点,所以时间戳是跨平台的统一时间表示。
import time
from datetime import datetime
# 获取当前时间戳(浮点数,带小数部分)
timestamp = time.time()
print(f"当前时间戳:{timestamp}")
print(f"整数部分(秒):{int(timestamp)}")
print(f"小数部分(微秒):{timestamp - int(timestamp):.6f}")
# 时间戳 → 人类可读时间
readable = datetime.fromtimestamp(timestamp)
print(f"时间戳转日期:{readable}")
# 人类可读时间 → 时间戳
dt = datetime(2026, 7, 1, 12, 0, 0)
ts = dt.timestamp()
print(f"日期转时间戳:{ts}")
5.2 结构化时间:time.localtime() 与 time.gmtime()
time.localtime() 把时间戳解析成一个结构化时间对象(struct_time),包含年月日时分秒等各个字段。
import time
now = time.localtime()
print(f"类型:{type(now)}") # <class 'time.struct_time'>
# 通过索引或属性名访问各部分
print(f"年:{now.tm_year}") # 也可以用 now[0]
print(f"月:{now.tm_mon}") # 也可以用 now[1]
print(f"日:{now.tm_mday}") # 也可以用 now[2]
print(f"时:{now.tm_hour}") # 也可以用 now[3]
print(f"分:{now.tm_min}") # 也可以用 now[4]
print(f"秒:{now.tm_sec}") # 也可以用 now[5]
print(f"星期几(0=周一):{now.tm_wday}") # 也可以用 now[6]
print(f"一年第几天:{now.tm_yday}") # 也可以用 now[7]
# 格式化输出结构化时间
formatted = time.strftime("%Y-%m-%d %H:%M:%S", now)
# 注意:time.strftime 的第二个参数是 struct_time
print(f"格式化:{formatted}")
5.3 sleep:让程序暂停
import time
print("开始倒计时:")
for i in range(5, 0, -1):
print(f" {i}...")
time.sleep(1) # 暂停 1 秒
print("时间到!")
# sleep 支持小数
print("微停顿 0.5 秒...")
time.sleep(0.5)
print("继续")
5.4 程序运行时间统计
time.perf_counter() 是 Python 推荐用来精确计时的函数。它不受系统时间调整影响,精度高。
import time
# === 方法1:perf_counter(推荐,精度最高)===
start = time.perf_counter()
# 要做的事
total = 0
for i in range(10_000_000):
total += i
end = time.perf_counter()
elapsed = end - start
print(f"计算耗时:{elapsed:.4f} 秒")
# === 方法2:time.time() ===
# 也可以用,但受系统时间调整影响(比如 NTP 校时)
start = time.time()
# ... 执行操作 ...
end = time.time()
print(f"耗时(time):{end - start:.4f} 秒")
# === 方法3:timeit 模块(用于小段代码的精确计时)===
import timeit
code_to_test = """
total = 0
for i in range(1000):
total += i
"""
execution_time = timeit.timeit(code_to_test, number=10000)
print(f"10000次执行总耗时:{execution_time:.4f} 秒")
5.5 time 与 datetime 的区别与协作
import time
from datetime import datetime
# time 关注:时间戳、精确计时、毫秒间隔
# datetime 关注:日历日期、格式化、日期加减
# === 互相转换 ===
# time 时间戳 → datetime
ts = time.time()
dt = datetime.fromtimestamp(ts)
print(f"时间戳 → datetime:{dt}")
# datetime → time 时间戳
ts_from_dt = dt.timestamp()
print(f"datetime → 时间戳:{ts_from_dt}")
# datetime → time 结构化时间
dt = datetime.now()
struct = dt.timetuple()
print(f"datetime → struct_time:{struct}")
# time 结构化时间 → datetime
dt2 = datetime.fromtimestamp(time.mktime(struct))
print(f"struct_time → datetime:{dt2}")
| 场景 | 用哪个 | 原因 |
|---|---|---|
| 显示"2026年7月1日" | datetime |
日历显示是 datetime 的专长 |
| 计算"距离开学还有几天" | datetime |
timedelta 做日期加减最方便 |
| 统计代码运行耗时 | time.perf_counter() |
精度最高 |
| 让程序等待 2 秒 | time.sleep(2) |
简单直接 |
| 存储"事件发生的时间" | datetime + timestamp() |
datetime 存成时间戳,通用 |
| 生成文件名加时间戳 | int(time.time()) |
简单唯一 |
课堂练习题 — time 模块
练习 1:写一个"10 秒倒计时"程序,每秒打印一次剩余秒数。
练习 2:用 time.perf_counter() 计算 sum(range(10_000_000)) 的执行时间。
练习 3:获取当前时间戳,转成 datetime 对象,再转回时间戳。验证转换前后是否一致。
六、random 模块:随机数生成
6.0 模块定位
random 模块让你在程序中引入随机性。比如抽奖、随机排序、生成验证码、掷骰子游戏等。
生活类比:random 就像掷骰子、抽扑克牌、转幸运转盘——结果不确定,但公平随机。
import random
重要说明:random 生成的是伪随机数——用算法算出来的,看起来随机但不是真正的随机。对于抽奖、游戏等场景足够用;如果需要密码学级别的真随机,请用 secrets 模块。
6.1 基础随机数生成
import random
# === 随机浮点数 ===
print(f"0 到 1 之间:{random.random()}") # [0.0, 1.0) 比如 0.723456
print(f"a 到 b 之间:{random.uniform(1, 10)}") # [1.0, 10.0] 比如 5.23
# === 随机整数 ===
print(f"1 到 10(含10):{random.randint(1, 10)}") # 包含两端 [1, 10]
print(f"1 到 10(不含10):{random.randrange(1, 10)}") # 不含右端 [1, 10)
print(f"0-100 的偶数:{random.randrange(0, 101, 2)}") # 步长 2,取偶数
# === 设置随机种子(固定随机结果,方便复现调试)===
random.seed(42)
print(f"种子 42 的第一个随机数:{random.random()}")
random.seed(42)
print(f"种子 42 的第二个(重新设置种子):{random.random()}")
# 设置相同种子后,随机序列完全一样,这对调试和测试很有用
6.2 从序列中随机选择
import random
# 一组奖品
prizes = ["一等奖", "二等奖", "三等奖", "参与奖", "参与奖"]
# 随机选一个
winner = random.choice(prizes)
print(f"恭喜你抽中:{winner}")
# 随机选多个(无放回抽样——已经抽过的不再抽)
sample_3 = random.sample(prizes, 3)
print(f"抽 3 个:{sample_3}")
# 随机选多个(有放回——可以重复抽)
choices_3 = random.choices(prizes, k=3)
print(f"有放回抽 3 个:{choices_3}")
6.3 加权随机选择
import random
# 抽奖池:奖品和对应的权重
prizes = ["iPhone", "iPad", "耳机", "谢谢参与"]
weights = [1, 3, 10, 86] # 权重:iPhone最难抽到
# iPhone 权重 1,iPad 权重 3,耳机权重 10,谢谢参与权重 86
# iPhone 概率 ≈ 1/(1+3+10+86) = 1%
winner = random.choices(prizes, weights=weights, k=1)[0]
print(f"抽奖结果:{winner}")
# === 模拟抽奖 10000 次,看各奖品出现次数 ===
results = random.choices(prizes, weights=weights, k=10000)
for prize in prizes:
count = results.count(prize)
print(f"{prize}:{count} 次 ({count/100:.1f}%)")
# 可能的输出:
# iPhone:108 次 (1.1%)
# iPad:307 次 (3.1%)
# 耳机:1015 次 (10.2%)
# 谢谢参与:8570 次 (85.7%)
6.4 打乱序列顺序
import random
# 一副扑克牌(简化版)
cards = ["A♠", "K♠", "Q♠", "J♠", "10♠",
"A♥", "K♥", "Q♥", "J♥", "10♥"]
print(f"洗牌前:{cards}")
random.shuffle(cards) # 原地打乱,直接修改原列表
print(f"洗牌后:{cards}")
# 注意:shuffle 修改原列表!如果不想改原列表:
original = [1, 2, 3, 4, 5]
shuffled = random.sample(original, len(original)) # 返回新列表
print(f"原列表(不变):{original}")
print(f"打乱后的新列表:{shuffled}")
6.5 趣味教学案例
案例 1:课堂随机点名器
import random
students = ["张三", "李四", "王五", "赵六", "孙七", "周八", "吴九"]
print("=== 随机点名器 ===")
print("1. 点名单个学生")
print("2. 随机分组")
print("3. 抽选三位同学")
choice = input("请选择功能:")
if choice == "1":
# 每次点名一个人,按回车继续
while True:
input("按回车开始点名...")
name = random.choice(students)
print(f"\n >> 点到:{name}!\n")
elif choice == "2":
# 随机平均分组
random.shuffle(students)
group_size = len(students) // 3
groups = [students[i:i+group_size] for i in range(0, len(students), group_size)]
for i, group in enumerate(groups, 1):
print(f"第 {i} 组:{', '.join(group)}")
elif choice == "3":
picked = random.sample(students, 3)
print(f"被抽中的三位同学:{', '.join(picked)}")
案例 2:生成随机验证码
import random
import string
def generate_code(length=6):
"""生成指定长度的随机验证码(数字+字母)"""
chars = string.ascii_letters + string.digits # a-z A-Z 0-9
code = ''.join(random.choices(chars, k=length))
return code
def generate_easy_code(length=4):
"""生成易读验证码(无易混淆字符:0/O, 1/l/I, 2/Z)"""
safe_chars = "3456789ABCDEFGHJKLMNPQRSTUVWXY"
return ''.join(random.choices(safe_chars, k=length))
for _ in range(5):
print(f"验证码:{generate_code()} 易读版:{generate_easy_code()}")
# 输出示例:
# 验证码:Kx7mPq 易读版:H4TN
# 验证码:aB9dE2 易读版:7WXY
# 验证码:Rt5yGh 易读版:A3MN
案例 3:模拟骰子游戏
import random
def roll_dice(sides=6, count=1):
"""掷骰子"""
results = [random.randint(1, sides) for _ in range(count)]
if count == 1:
return results[0]
return results
# 掷一个骰子 10 次
print("掷十次骰子:", end="")
for _ in range(10):
print(roll_dice(), end=" ")
print()
# 同时掷两个骰子
print("掷两个骰子(每次显示两个数):")
for _ in range(5):
a, b = roll_dice(count=2)
print(f" [{a}] [{b}] → 合计 {a + b}")
案例 4:幸运大转盘
import random
# 转盘奖品(带权重)
wheel = {
"🎁 iPhone 15": 1,
"🎧 AirPods": 3,
"☕ 奶茶券": 15,
"📦 笔记本": 20,
"😅 谢谢参与": 61,
}
prizes = list(wheel.keys())
weights = list(wheel.values())
print("=== 幸运大转盘 ===")
print("奖品分布:")
for prize, weight in zip(prizes, weights):
prob = weight / sum(weights) * 100
print(f" {prize}:{prob:.1f}%")
print("\n开始抽奖!")
input("按回车转动转盘...")
result = random.choices(prizes, weights=weights, k=1)[0]
print(f"\n ✨ 恭喜获得:{result} ✨\n")
课堂练习题 — random 模块
练习 1:模拟抛硬币 1000 次,统计正面和反面的次数。
练习 2:班上有 30 人,随机分成 5 组,每组 6 人,打印分组结果。
练习 3:实现一个"猜数字"游戏:程序随机生成 1-100 的整数,用户猜,提示"大了"或"小了"直到猜对。
练习 4:用 random.choices() 配合权重模拟一个"抽 SSR 卡牌"的抽卡系统(SSR 概率 3%,SR 概率 15%,R 概率 82%),模拟抽 100 次的结果。
练习 5:自定义字母和数字池(去掉易混淆字符),生成 10 个长度为 8 的随机密码。
总结
六大模块速查表:
┌──────────┬────────────────────────────┬──────────────────────────────┐
│ 模块 │ 一句话定位 │ 最常用的 3 个功能 │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ os │ 操作系统的翻译官 │ listdir(), makedirs(), │
│ │ │ path.join() │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ sys │ Python 解释器的仪表盘 │ argv, exit(), path │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ math │ 科学计算器 │ sqrt(), pi, sin()/cos() │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ datetime │ 电子台历 │ datetime.now(), timedelta(), │
│ │ │ strftime()/strptime() │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ time │ 秒表 │ time(), sleep(), │
│ │ │ perf_counter() │
├──────────┼────────────────────────────┼──────────────────────────────┤
│ random │ 骰子/抽奖转盘 │ choice(), shuffle(), │
│ │ │ randint() │
└──────────┴────────────────────────────┴──────────────────────────────┘
学习建议:
- 先记住每个模块的"一句话定位",知道什么时候该用谁
- 每个模块练熟 3 个最常用功能,其余需要时查文档
- os.path 和 pathlib 二选一学习即可(推荐 pathlib,更现代)
- datetime 和 time 经常配合使用,理解它们的分工很重要
- random 多写趣味案例,学起来轻松愉快
祝教学愉快,学习顺利!