"人生苦短,我用 Python。"这不是一句口号,是无数程序员血泪换来的结论。这一页把 Python 从"装环境"讲到"写出能交付的命令行小工具"——语法、数据结构、函数、面向对象、装饰器、异常、模块包、文件 IO、并发异步、测试,外加一个待办事项小项目。版本基线:Python 3.13(2024 年 10 月发布,当前稳定主力)与 Python 3.14(2025 年 10 月发布,最新)。Python 2 已于 2020 年正式停更,别再回头。
| 版本 | 状态 | 要点 |
|---|---|---|
| Python 3.14 | 最新稳定 | 2025 年 10 月发布,当前最新稳定版;自由线程(no-GIL)与 JIT(copy-and-patch)按官方节奏推进,具体新特性以官网发布说明为准。 |
| Python 3.13 | 当前主力 | 2024 年 10 月发布,生态最稳、第三方库适配最全;自由线程(no-GIL)为实验性,需用 --disable-gil 开关启用;copy-and-patch JIT 同为实验性。 |
| Python 3.12 | 广泛使用 | 上一代稳定版,大量生产环境仍在跑;错误提示更友好,性能小幅提升。新项目建议直接上 3.13 / 3.14。 |
| Python 2.x | 已停更 | 2020 年 1 月 1 日 EOL(End Of Life),官方不再发安全补丁。网上老教程里 print "hi"(无括号)全是 Python 2 写法,别照抄。 |
包管理与虚拟环境速查
| 类别 | 工具 | 说明 |
|---|---|---|
| 包管理 | pip 25.x | 标准包管理器,pip install xxx,所有项目都绕不开。 |
| uv | Astral 出品的超快包管理器(Rust 写的),比 pip 快 10-100 倍,兼容 pip 接口,新项目强烈推荐。 | |
| poetry 1.8.x | 带依赖锁定和虚拟环境管理,pyproject.toml 一站式,适合正式开源库。 | |
| conda | 科学计算专用,连 Python 解释器一起管,处理 NumPy/PyTorch 等 C 扩展库时省心。 | |
| 虚拟环境 | venv | 标准库自带,python -m venv .venv,轻量够用。 |
| virtualenv | venv 的加强版,Python 3.3 之前的老方案,现在基本被 venv 取代。 | |
| conda env | conda 自带的环境隔离,和 conda 配套用。 |
Python 3.13 的自由线程(no-GIL)和 copy-and-patch JIT 都还是实验性:自由线程要编译/下载专门版本并用 --disable-gil 启动,很多 C 扩展库(NumPy、Pillow 等)还没完全适配;JIT 更早期,效果因场景而异。生产环境先用标准 3.13 / 3.14,等 3.14 之后官方宣布正式化再迁移。别为了"消灭 GIL"把自己坑进兼容性地狱。
本页目录
- 为什么学 Python & 环境搭建
- 基础语法:变量、类型、流程控制
- 四大数据结构:list / tuple / dict / set
- 函数:参数、作用域、lambda、高阶函数
- 面向对象:class、继承、property、dataclass
- 装饰器与生成器:yield、itertools
- 异常处理:try/except、with、自定义异常
- 模块与包:pip、venv、pyproject.toml
- 文件与 IO:CSV、JSON、pathlib
- 并发与异步:threading / multiprocessing / asyncio
- 测试与调试:pytest、pdb、logging
- 小项目:命令行待办事项工具
- 常见坑与最佳实践
- 打包与发布:wheel / pyproject / uv
- CPython 性能与剖析
- C 扩展与 FFI(ctypes / cffi / pyo3)
为什么学 Python & 把环境装上
Why Python & Setup
基础语法:变量、类型、流程控制
Variables, Types & Flow Control
四大数据结构
list / tuple / dict / set
函数:把动作打包成按钮
Functions, Parameters & Scope
面向对象 OOP
Classes, Inheritance & dataclass
装饰器与生成器
Decorators & Generators
异常处理:别让程序一句话崩
try / except / with
模块与包:组织你的代码
Modules, Packages & pip
文件与 IO
Files, CSV, JSON, pathlib
并发与异步
threading / multiprocessing / asyncio
测试与调试
pytest, pdb, logging
小项目:命令行待办事项工具
Mini Project: CLI Todo
常见坑与最佳实践
Pitfalls & Best Practices
小结 & 自测题
到这里,你已经从"装 Python"走到了"写一个命令行工具"。Python 的精髓不是记住所有语法,而是知道有什么、需要时能查。下面 5 道题,遮住答案自己答一遍。
1.(概念题)Python 里 list 和 tuple 最本质的区别是什么?什么时候你会特意用 tuple?
查看答案
答案:list 可变,tuple 不可变。当数据不该被改(坐标、函数多返回值、当字典键)时用 tuple。解析:不可变是一种"约束"——它告诉读代码的人"这东西别乱动",同时 tuple 能当字典的键,list 不行。
2.(代码题)下面代码输出什么?为什么?
查看答案
答案:第一次 ['hi'],第二次 ['hi', 'hi']。解析:这就是著名的"可变默认参数坑"——默认列表在函数定义时只创建一次,两次调用共用同一个列表。修法:def f(x=None): if x is None: x = []。
3.(概念题)为什么 Python 的多线程不适合加速"CPU 密集型"任务?该用什么?
查看答案
答案:因为 GIL(全局解释器锁)——同一时刻一个进程里只有一个线程跑 Python 字节码,多线程在 CPU 密集任务上等于排队。CPU 密集型应该用 multiprocessing 多进程(绕开 GIL)。IO 密集型才用线程或 asyncio。
4.(代码题)用列表推导式,把 [1,2,3,4,5,6] 变成每个偶数的平方,结果是?
查看答案
答案:[x*x for x in [1,2,3,4,5,6] if x % 2 == 0] → [4, 16, 36]。解析:前半段 x*x 是加工,if x%2==0 是筛选。推导式一行顶三行循环。
5.(思考题)你写了一个爬取 1000 个网页的脚本,串行要 10 分钟,想提速。你会选多线程还是多进程?为什么?
查看答案
答案:选多线程(或 asyncio)。解析:爬虫的时间几乎全花在"等网络返回"上,是 IO 密集型。GIL 在等网络时会释放,多线程能真正并行等。用多进程纯属浪费——创建进程贵,而且 CPU 根本没在算东西。最佳是 asyncio + aiohttp,几千个请求同时飞。
综合练习题(5 道,覆盖全章)
1.(代码题)写一个带参数的装饰器 @log_calls(prefix="[API]"),打印每次调用的函数名、参数和前缀。要求用 functools.wraps。
查看答案
答案:三层结构——外层接参数 prefix,中层接函数,内层接调用。wrapper(*a, **kw) 里先 print 前缀+函数名+参数,再调原函数。别忘 @wraps(func)。这是带参装饰器的固定套路。
2.(代码题)用生成器写一个"读超大日志文件,逐行 yield 错误行"的函数,要求内存恒定(不能 read() 整个文件)。
查看答案
答案:def iter_error_lines(path): 里 with open(path) as f: for line in f: if "ERROR" in line: yield line.rstrip()。解析:文件对象本身就是迭代器,for line in f 逐行缓冲不读全文件;yield 出去调用方处理完才拉下一行——几个 G 的日志也只占一行内存。
3.(代码题)用 ThreadPoolExecutor 并发下载 5 个 URL 的状态码,要求"谁先下完先打印谁",并统计总耗时。
查看答案
答案:pool.submit 每个任务一次,存进 {fut: url} 字典;as_completed(futs) 按完成先后迭代,fut.result() 拿结果。解析:as_completed 适合流式打印,max_workers 5-20 足够,开太多反而被限流。
4.(代码题)写一个异步协程 fetch_all(urls),用 aiohttp 并发抓取,Semaphore 限制同时最多 10 个,返回 {url: status_code}。
查看答案
答案:建 sem = asyncio.Semaphore(10),内部 one(u) 在 async with sem 里 async with s.get(u) as r: return u, r.status;外层 dict(await asyncio.gather(*[one(u) for u in urls]))。解析:Semaphore 限流防封 IP,gather 汇总成 (url, status) 配对,dict() 反转成映射。
5.(思考题)你有一个 100 万行的 CSV,要统计其中"价格 > 100 的行数"。用 sum(1 for row ...) 和 len([...]) 哪个好?为什么?
查看答案
答案:用生成器表达式 sum(1 for row in reader if price>100)。len([...]) 会先建 100 万元素的列表占内存再数长度;生成器边读边数,内存恒定。这就是"能用生成器就别用列表"的典型场景。
① 动手:把 todo 项目加个"优先级"和"按日期筛选"功能。
② 写点真脚本:拿你每周重复的一件事,写成 Python。
③ 进 AI 方向:Python 基础打底之后,下一页就是 Python AI 数据科学——NumPy、Pandas、PyTorch。