Python 概览
自动关联目录:Python 概览
设计取舍
| 取舍 | 换来什么 | 代价 |
|---|---|---|
| 动态类型 + 解释执行 | 写得快、改得快 | 运行慢,重构靠工具 |
| 一切皆对象 | 语义统一、反射方便 | 内存开销大(一个 int 约 28 字节) |
| GIL | 实现简单、单线程快、C 扩展易写 | 多线程无法利用多核 |
| 强制缩进 | 格式天然统一 | 复制粘贴容易出错 |
| 庞大标准库 | 开箱即用 | 标准库风格不统一(历史包袱) |
内建容器怎么选
| 容器 | 是否有序 | 是否可变 | 典型用途 | 复杂度 |
|---|---|---|---|---|
list | 是 | 是 | 通用序列、栈 | 尾部增删,头部 |
tuple | 是 | 否 | 固定结构、字典键 | —— |
dict | 是(插入序) | 是 | 映射、计数 | 平均 |
set | 否 | 是 | 去重、成员判断 | 平均 |
deque | 是 | 是 | 队列(两端操作) | 两端 |
heapq | 部分 | 是 | 优先级队列 | 推/弹 |
循环里判断成员用 set 而不是 list——这是最常见的"改一个词快十倍"。
迭代器与生成器
生成器(yield)是 Python 里最实用的抽象之一:
| 好处 | 说明 |
|---|---|
| 惰性 | 不一次性构造全部数据,省内存 |
| 可组合 | 管道式处理,读起来像流水线 |
| 支持无限序列 | 理论上可以一直产出 |
def read_lines(path):
with open(path) as f:
for line in f:
yield line.rstrip("\n")注意生成器只能遍历一次,需要复用就转成 list。
GIL 到底限制了什么
GIL(全局解释器锁)保证同一时刻只有一个线程执行 Python 字节码。
| 场景 | 多线程是否有效 |
|---|---|
| CPU 密集(纯 Python 计算) | 无效,甚至因为切换更慢 |
| IO 密集(网络、磁盘) | 有效,IO 时会释放 GIL |
| NumPy / C 扩展的大块计算 | 有效——扩展里可以主动释放 GIL |
所以:CPU 密集用 multiprocessing,IO 密集用 asyncio 或线程池。
常见性能陷阱
| 陷阱 | 改法 |
|---|---|
循环里 str += | ''.join(list)(CPython 有优化,但别依赖) |
循环里 list 成员判断 | 转 set |
| 逐元素数值计算 | NumPy 向量化 |
频繁 dict[key] + try/except | dict.get 或 collections.defaultdict |
| 大量小对象 | __slots__、或用 array/NumPy |
反复 len() 在条件里 | 通常无所谓,但热循环里先取出来 |
语言特性速查
| 特性 | 用途 |
|---|---|
| 列表/字典推导式 | 简洁构造,别嵌套超过两层 |
| 装饰器 | 无侵入地加行为(计时、缓存、注册) |
上下文管理器 with | 资源自动释放 |
*args / **kwargs | 可变参数与转发 |
| 切片 | a[::2]、a[::-1] |
| 解包 | a, *rest = xs、{**d1, **d2} |
functools.lru_cache | 一行加记忆化 |
| 类型注解 | 配合 mypy,规模化的前提 |
与 C++ 的思维差异
| 从 C++ 过来要注意 | 说明 |
|---|---|
| 没有真正的私有 | _name 只是约定 |
| 循环变量泄漏 | for 结束后变量仍在作用域 |
is 与 == | is 比身份,== 比值;小整数有缓存陷阱 |
| 深浅拷贝 | copy.copy vs copy.deepcopy |
没有 switch | 3.10 起有 match |
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/672e263e.html
更新于:2026年10月10日