Python FAQ
内容:
- 基础语法
- 数据结构
- 进阶特性
- 面向对象
- 函数式编程
- 并发(多线程、异步、进程)
- 网络与文件
- 标准库
- 高级机制
- 项目实战
- 性能优化
- 常见陷阱
完全适用于 Python 开发 / 爬虫 / 数据工程 / 后端。
- 解释型、动态类型
- 强类型
- 跨平台
- 拥有丰富标准库
- 面向对象、函数式风格都支持
- 可读性好、开发效率高
| 列表 list | 元组 tuple |
|---|---|
| 可变 | 不可变 |
| 适合动态数据 | 适合固定结构数据 |
| 占用更大内存 | 内存更小,速度更快 |
| append / pop | 无修改方法 |
实战经验:
数据不会变化时应优先选择 tuple,可以用于 dict key。
- 引用计数(primary GC)
- 标记-清除(处理循环引用)
- 分代回收机制
- == 比较值
- is 比较对象引用(是否是同一个对象)
copy.copy() # 浅拷贝,只复制最外层
copy.deepcopy() # 深拷贝,递归复制所有层级
- 不可变:int, float, str, tuple, frozenset
- 可变:list, dict, set
具有 __iter__ 或 __getitem__ 方法的对象。
如:list, tuple, dict, set, file, range, generator
使用 yield 返回的函数,惰性计算、节约内存。
- L: Local
- E: Enclosing
- G: Global
- B: Built-in
本质是一个接受函数并返回新函数的高阶函数,用于:
- 日志
- 权限控制
- 缓存
- 性能统计
示例:
def deco(fn):
def wrapper(*a, **kw):
print("before")
return fn(*a, **kw)
return wrapper
| 操作 | list | tuple | set | dict |
|---|---|---|---|---|
| 访问 | O(1) | O(1) | N/A | O(1) |
| 插入 | O(n) | 不支持 | O(1) | O(1) |
| 删除 | O(n) | 不支持 | O(1) | O(1) |
| 查找 | O(n) | O(n) | O(1) | O(1) |
因为使用哈希表存储,通过 key 的 hash 定位 bucket。
和 dict 类似,也是哈希表,不存 value。
sorted(d.items(), key=lambda x: x[1])
列表推导式可读性更好:
[x*x for x in lst if x>0]
打包多个可迭代对象,返回 tuple:
zip([1,2], ["a","b"]) -> [(1,"a"), (2,"b")]
获取(索引, 值):
for i, v in enumerate(items, start=1):
lst[::-1]
list(reversed(lst))
{x: x*x for x in range(5)}
因为内部没有 lock,多线程 append 时会竞争资源。
函数内部引用外部变量,并在函数返回后仍然有效。
匿名函数,可读性差,功能有限。
接收任意数量的位置参数和关键字参数。
callable(obj)
| 类型 | 第一个参数 | 用途 |
|---|---|---|
| staticmethod | 无 | 工具函数 |
| classmethod | cls | 类级行为(工厂方法) |
| property | self | 伪属性 |
执行 MRO(方法解析顺序)链上的下一个类方法。
使用 C3 MRO。
- 自动生成 init、repr
- 支持类型注解
- 可选 frozen=True(不可变)
限制实例属性,减少内存占用、提高访问速度。
上下文管理器(with)。
全局解释器锁,使同一时刻只能有一个线程执行 Python 字节码。
| ThreadPool | ProcessPool |
|---|---|
| 受 GIL 限制 | 不受 GIL |
| 适合 IO | 适合 CPU |
| 轻量 | 重 |
事件循环 + 协程 + 可等待对象。
声明协程,用于异步 IO。
- 协程最轻
- 线程中等
- 进程最重(拥有独立内存)
- 创建事件循环
- 执行协程
- 关闭循环
使用 Lock:
lock = threading.Lock()
with lock:
...
loop.run_in_executor(ProcessPoolExecutor(), func)
- queue.Queue:线程安全
- asyncio.Queue:异步任务间通信
因为 Windows 采用 spawn,必须可序列化。
自动关闭文件,防止资源泄漏。
使用流式读取:
for line in f:
用 parse_float=Decimal 或 orjson。
因为它基于阻塞 IO。
requests 更易用、功能更强。
stream=True
Path.exists()
使用参数绑定,禁止拼接。
from urllib.parse import urlparse, parse_qs
使用锁。
创建类的类(控制类的行为)
运行时修改类或模块。
- getattr:属性不存在时调用
- getattribute:所有属性访问都会调用
实现 __get__, __set__, __delete__ 的类,用于控制属性行为。
对象实现:
__iter____next__
将子生成器的值自动传递给外层生成器:
yield from sub_generator()
缓存函数返回值,提高性能。
避免隐藏 stack trace,保持 debug 能力。
保留原函数的元数据(名字、文档)。
不是通过“类型”判断,而是通过“行为”判断。