简介:这是一份面向 Python 求职者与基础学习者的面试知识点速查 PDF,聚焦生成器、迭代器、列表与元组、字典实现、GIL 全局解释器锁、Py2/Py3 差异、可变与不可变对象、闭包与装饰器等高频问题,以问答形式给出精炼结论与代码示例,适合笔试面试前快速回顾。资源仅含 1 个 PDF 文件,压缩包约 304KB,体积轻巧,可随时在手机或电脑上查阅;目前已有 13637 人学习下载。除核心八股外,内容还延伸到 list/dict 底层存储原理、多线程与多核 CPU 的关系、元类的定义与使用场景等进阶话题,并配有 fib 生成器、计时装饰器、迭代器判断等常见片段,能帮助读者把零散知识点串成体系,补足易被追问的细节。PDF 按问题组织内容,从内置电池概念到多线程 GIL 均有涉及,适合系统性梳理与考前冲刺。
1. Python 八股文.pdf 的本质:把知识压缩成可检索的索引
很多候选人手里都有一份 Python 八股文.pdf,里面罗列着 GIL、装饰器、迭代器、MRO 这类高频问题。可现实是,背完这份 PDF 的人,往往能在选择题里拿高分,却在面试现场被一句“你能举个例子吗”卡住。原因很简单:八股文只给了“最常用的结论”,没给你“结论背后的推导链”。这篇文章不是让你再背一遍,而是让你把这份 PDF 当成一个入口:看清每个知识点被拿出来问的真实动机,知道怎么整理、怎么验证、怎么把它讲成面试官愿意听到的答案。适合正在准备 Python 岗位的求职者,也适合想系统梳理基础概念的初级开发。读完你会得到一套从“背”走向“用”的方法。
2. 拆开 Python 八股文:四块必考地基与它们的底层逻辑
整份 PDF 看似散乱,其实知识点都压在四个地基上:对象模型、函数语法糖、面向对象体系、并发与内存管理。任何一个追问,最后都会落到这四个域里。下面按域拆开,每个都给最小示例和面试官真正的考察点。
2.1 对象模型与内建容器:is与==只是开胃菜
先看最经典的一段:
a = [1, 2] b = [1, 2] print(a is b) # False:两个列表对象不同 print(a == b) # True:值相同 c = 256 d = 256 print(c is d) # True:小整数被缓存为单例 e = 257 f = 257 print(e is f) # 通常 False:超出缓存范围,创建新对象is比较的是对象身份(内存地址),==比较的是值。小整数从 -5 到 256 会被解释器缓存成单例,所以c is d返回 True;超出这个范围,每次字面量都会创建新对象,e is f一般返回 False。这里“一般”是因为不同解释器、不同运行方式(交互式命令行和脚本文件)对整数字面量的复用策略不完全一致,八股文里如果只写“257 是 False”就容易翻车。
面试官把这个放在第一题,看的是你分不分得清“值相等”和“对象相同”这两个维度。如果你能进一步说出“in做容器查找时靠__eq__,dict的 key 额外还要算__hash__”,说明你对对象模型有整体认识。很多容器相关的坑都来自这里:把可变对象放进set会报TypeError,因为列表不可哈希;自定义类不重写__hash__就放进字典,两个“相等”的实例会被当作两个 key。
另一处高频点是“可变默认参数”。我在整理 PDF 时专门把这个例子放了一页:
def add_item(item, cache=[]): # 默认参数在定义时只创建一次 cache.append(item) return cache print(add_item(1)) # [1] print(add_item(2)) # [1, 2]:共享了同一个列表默认参数在函数定义时只求值一次,cache指向同一个列表对象,所以多次调用会累积。修法要么用None再在函数体内创建新列表,要么用cache: list | None = None。这个考的不是语法,而是“对象什么时候创建、什么时候被共享”的执行模型。
所以整理这块时,我建议你在每个知识条目下固定写四行:
- 一句话结论
- 最小代码片段
- 内存/对象层面的原因
- 一个能直接用于生产的修正写法
这样 PDF 就不是背的,而是排查问题时的索引。
2.2 函数语法糖:装饰器、生成器、上下文管理器
这三个概念在 PDF 里常被分到不同小节,但在运行时本质上都依赖“函数对象可以被保存和传递”这一事实。装饰器是闭包的典型应用:
import functools import time def elapsed(func): @functools.wraps(func) # 保留原函数的元信息 def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) print(f"{func.__name__} cost {time.perf_counter() - start:.4f}s") return result return wrapper @elapsed # 等价于 sleep_a_little = elapsed(sleep_a_little) def sleep_a_little(): time.sleep(0.1) sleep_a_little()@elapsed等价于sleep_a_little = elapsed(sleep_a_little)。wrapper捕获了外层的func,这就是闭包。functools.wraps会把原来函数的__name__、__doc__复制到wrapper上,否则被装饰后函数名会变成wrapper,八股文里如果不提这一点,面试追问“装饰器对函数元信息的影响”就会卡住。
参数说明:*args收集位置参数,**kwargs收集关键字参数,这样装饰器才能包住任意签名的函数。time.perf_counter()提供高精度计时。这段代码可以直接保存成decorator_demo.py运行,不需要外部依赖。
生成器的考点更偏向状态保存:
def fibonacci(): a, b = 0, 1 while True: yield a # 暂停并保存当前状态 a, b = b, a + b fib = fibonacci() # 此时函数体不会执行 for _ in range(5): print(next(fib)) # 输出 0 1 1 2 3yield会把函数变成生成器对象,next()每次从上次暂停的地方继续。和一次性返回列表相比,生成器不保存完整序列,适合流式处理大文件。面试官通常会让“手写一个生成器”,你要能说出“函数体里只要有yield,调用函数时不会执行函数体,只返回生成器对象”。
上下文管理器则考察“资源释放”的执行顺序:
class ManagedFile: def __init__(self, filename, mode): self.filename = filename self.mode = mode def __enter__(self): # 进入 with 块时调用 self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_value, traceback): self.file.close() return False # False 表示不抑制异常 with ManagedFile("hello.txt", "w") as f: f.write("hello")__exit__返回False表示异常不会被吞掉;如果返回True,异常会被抑制,这通常是八股文里的隐藏考点。with能保证即使写入过程抛异常也会调用__exit__,这就是“资源安全”的关键。
这三个例子放在同一节,是因为面试官经常把它们混在“Python 的函数式能力”里考。你整理 PDF 时,建议把“闭包、惰性求值、资源释放”三者的触发场景对比成表格,比如“装饰器是外层函数返回内层函数,生成器是函数执行变成状态机,上下文管理器是协议方法保证清理”。
2.3 面向对象与继承:MRO、super、__slots__
菱形继承是必考:
class A: def who(self): print("A") class B(A): def who(self): print("B") super().who() # 按 MRO 找下一个类 class C(A): def who(self): print("C") super().who() class D(B, C): pass d = D() d.who()输出顺序是B C A,而不是B A。因为 Python 用 C3 线性化算法计算 MRO,D的 MRO 是D -> B -> C -> A -> object。super()不是“父类”,而是按 MRO 的下一个类继续查找。如果你在整理这份 PDF 时只写“super()用于调用父类方法”,面试官一追问“那 C 的who为什么会被调用”就答错了。
代码逻辑说明:B.who中调用super().who(),它按D的 MRO 找B后面的类,也就是C。所以打印完B后进入C.who,打印C后再调到A.who。想要验证 MRO,可以直接打印D.__mro__,输出会是一串类对象,这也应该写进你的 PDF 示例。
__slots__常被当作“优化手段”考:
class Point: __slots__ = ("x", "y") # 固定允许的属性名 def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) # p.z = 3 # AttributeError:没有 __dict__ 支持普通实例会有一个__dict__来存储实例属性,__slots__用固定长度描述符替代它,所以不能添加新属性,但能显著降低内存占用。注意:如果类存在__slots__,又没有在基类加__slots__,子类仍然会生成__dict__。这一条属于典型的“知道结论但不知道边界”,PDF 里需要专门标注。
面向对象这块,八股文常考“__new__和__init__的区别”“抽象基类怎么用”“类变量和实例变量的查找顺序”。你可以把每个问题都写成“代码 + 输出 + MRO/查找链”的结构,面试官稍稍深挖,你就能顺着查表讲出来。
2.4 并发与内存管理:GIL、引用计数与垃圾回收
GIL 是 Python 八股文里存在感最强的概念。代码演示比纯背诵更直观:
import threading import time counter = 0 def add(): global counter for _ in range(1000000): counter += 1 # 读、加、写三步并非原子操作 threads = [threading.Thread(target=add) for _ in range(2)] start = time.time() for t in threads: t.start() for t in threads: t.join() print(counter, time.time() - start)在官方解释器中,这个程序运行后counter通常不是 2000000,甚至可能出现随机值。原因不只是 GIL,还有+=不是原子操作:它要经过“读、加、写”三步,两个线程可能在中间交错。哪怕有 GIL,线程切换也可能发生在字节码指令之间,所以仍然要加锁。
GIL 的全称是全局解释器锁,它让同一进程里同一时刻只有一个线程能执行 Python 字节码。引入它的初衷是保护内存管理——官方解释器用引用计数管理对象,如果不加全局锁,多个线程同时修改引用计数会导致内存错误。代价是无法利用多核做 CPU 密集并行。因此八股文的标准结论是:I/O 密集用多线程,CPU 密集用多进程。
内存管理这块,引用计数是主导:每个对象有一个计数,被引用就加一,删除就减一,减到零就回收。循环引用需要靠gc模块来清理。你可以用gc.get_objects()看当前对象数,用sys.getrefcount查看引用计数,但这些属于“验货手段”,不要在面试现场现查。
到这里你应该能发现,四块地基相互关联:对象模型解释is,闭包解释装饰器,MRO 解释继承,GIL 解释并发。PDF 里的问题只是入口,真正值钱的是你能把这些问题串成一张网。
3. 从零整理自己的 Python 八股文.pdf:骨架、示例与导出
我见过不少人的八股文 PDF 是从网上随便下载的,排版很好但内容庞杂,背了半个月还是记不住。更好的做法是按自己习惯整理。下面是我常用的流程,从 Markdown 骨架到可验证的示例,再到导出设置。
3.1 用目录和标签搭骨架,让知识点可检索
不要在 PDF 里做成“问答列表”,要做到“问题能被定位”。我一般先用 Markdown 建一个骨架:
# Python 八股文知识库 ## 1 对象模型 ### 1.1 == 与 is - 一句话结论 - 代码示例 - 底层原因 - 常见追问 ## 2 函数进阶 ### 2.1 装饰器 - 一句话结论 - 代码示例 - 底层原因 - 常见追问 ## 3 面向对象 ### 3.1 MRO - 一句话结论 - 代码示例 - 底层原因 - 常见追问 ## 4 并发与内存 ### 4.1 GIL - 一句话结论 - 代码示例 - 底层原因 - 常见追问这个结构的好处是,每个知识点固定四段,复习时只看“一句话结论”,理解时看“底层原因”,面试前重点看“代码示例”。你还可以在最前面用一个表格登记“掌握程度”:
| 知识点 | 结论 | 示例 | 底层 | 掌握度 |
|---|---|---|---|---|
| == 与 is | 已了解 | 已运行 | 未深究 | 60% |
表格里的掌握度每周更新一次,不熟悉的知识点单独抽出来重写。用标签分类也很有效:在标题后加[高频]、[易忘]、[版本敏感],导出 PDF 后能通过目录快速过滤。
3.2 给每个知识点配上能独立运行的示例,并自动验证
八股文 PDF 最怕代码跑不通。我的做法是在写出示例后,用一个脚本扫描全文代码块,检查语法是否能通过编译。下面这个脚本可以放在你的整理目录里,每次更新 Markdown 后跑一遍:
import pathlib import re def check_code_blocks(md_path: str) -> list[str]: text = pathlib.Path(md_path).read_text(encoding="utf-8") blocks = re.findall(r"```python\n(.*?)```", text, re.S) problems = [] for index, code in enumerate(blocks): try: compile(code, f"block_{index}", "exec") # 只编译不执行 except SyntaxError as exc: problems.append(f"Block {index} line {exc.lineno}: {exc.msg}") return problems if __name__ == "__main__": errors = check_code_blocks("python_bagu.md") if errors: print("Syntax errors found:") for e in errors: print(e) else: print("All python blocks are compilable.")逻辑说明:re.findall用非贪婪匹配抓取所有```python到```之间的文本,re.S让.能匹配换行。compile只做语法编译,不执行代码,避免你为了验证某段代码意外触发文件写入或网络请求。如果你想做更严的“运行验证”,可以在compile后调用exec,但必须在沙箱环境里,并且确认代码没有外部副作用。
参数说明:md_path是你的 Markdown 文件路径;index是代码块在文档里的顺序号;exc.lineno是出错行号,方便定位。这个脚本不需要第三方库,Python 3.8 以上都能跑。跑完如果提示All python blocks are compilable.,才能进入导出步骤。
3.3 导出 PDF 时重点调三处:目录、代码高亮、字体换行
内容整理好后,导出 PDF 不是简单点一下“打印”。以下三个设置直接影响复习体验:
| 设置项 | 建议值 | 原因 |
|---|---|---|
| 目录 | 生成可跳转的书签目录 | 面试前按章节快速定位 |
| 代码高亮 | 选择 Python 语法高亮 | 变量与关键字更容易分辨 |
| 字体/换行 | 中文字体 + 代码块自动换行 | 避免代码被截断,中文不显示为方框 |
具体操作因工具而异,但大方向是:先导出 HTML 再转 PDF,或在 Markdown 编辑器里选择“导出 PDF”并打开“包含目录”开关。如果你对排版有强迫症,可以在导出前检查两点:第一,所有代码块的缩进是否统一;第二,横向长度超过 80 字符的代码是否被换行,PDF 不会像编辑器那样给你横向滚动条。
导出后别急着结束,做一次“用户测试”:用阅读器搜索“GIL”,看能不能直接跳到对应页。我通常还会在 PDF 里加一页“索引表”,列出每个知识点的页码,这样在面试候场里翻起来最快。
3.4 把答案改写成自己的话,避免“背错版本”
整理 PDF 时最忌讳直接复制别人总结的语言。八股文之所以叫八股文,就是因为语言高度模板化,面试官一听就知道你在背。我的习惯是,每看到一个知识点,先照着代码运行一遍,然后关掉原文,用自己的话写一遍解释。写完和原文对比,如果发现表述不清,说明你还没懂。
比如“GIL”的标准解释是“全局解释器锁,限制同一时刻只有一个线程执行字节码”。用自己的话可以是“官方解释器为了让内存管理不被多线程搞乱,给解释器加了一把大锁;这把锁让 Python 线程无法在多个 CPU 核上同时算代码”。后者更像人话,也更接近面试官想要的答案。
这样整理出的 PDF 才有个人色彩,你在面试现场回忆时,会直接想起自己写的比喻,而不是背一串定义。
4. Python 八股文复习避坑:四个让背题失效的真实问题
“背题翻车”不是努力不够,而是方法踩了坑。下面四条是我整理和复习时踩过的,每一条都对应“现象→原因→解决”。
4.1 现象:背了所有答案,面试官一追问就卡壳
很多人把 PDF 从头到尾背了一遍,面试官问“defaultdict和dict的区别”能秒答,但继续问“为什么defaultdict能在访问不存在 key 时不抛异常”,就愣住了。原因是八股文只给了结论,没给结论建立在哪个机制上。defaultdict之所以不抛异常,是因为它重写了__missing__方法;普通dict访问不存在的 key 时,__getitem__会先触发__missing__,如果不存在该方法再抛KeyError。你只要把“__missing__”这个底层钩子说出来,面试官就知道你懂的是机制而不是死记。
from collections import defaultdict d = defaultdict(list) d["group"].append(1) print(d["group"]) # [1] print(d["nokey"]) # []:自动调用 __missing__ 生成默认值解决:整理 PDF 时,在每个知识点后面加一行“最深层的一个钩子是什么”。比如:
==对应__eq__in对应__contains__with对应__enter__/__exit__for对应__iter__/__next__
背熟这些钩子,追问就变成你主动展示的素材。
4.2 现象:把 Python 2 和 Python 3 的行为混着讲
我在一份旧八股文 PDF 里看到过“dict.keys()返回列表”,这在 Python 2 是对的,在 Python 3 返回视图对象。如果你面试时说“keys 返回列表”,面试官直接就能判断你资料过时。类似还有print是语句还是函数、range返回列表还是迭代器、字符串默认编码等等。原因不是你不懂,而是资料没标注版本。
解决:在 PDF 首页写清“以 Python 3.x 为主,差异点单独提示”。每个涉及版本行为的知识点,在标题后用[Py3]或[Py2/3差异]标记。复习到input/raw_input这类问题时,主动对比一下新老写法,并说一句“如果是 Python 3,应该用input,返回字符串;Python 2 的input会做 eval,有安全风险”。
4.3 现象:示例代码跑不通,或者复制后报 NameError
很多 PDF 里的代码为了排版省略了导入语句,例如直接写read_csv("data.csv")却不写导入和数据来源,或者用了自定义变量但不给定义。你照抄运行后报错,会怀疑是自己环境坏了,其实只是示例不自包含。面试时如果照搬这种片段,还会给面试官留下“你根本没跑过代码”的印象。
解决:在整理 PDF 时,所有示例遵循“自包含”原则:导入放最前,变量在同一段定义完整,尽量只用标准库。然后跑一遍我在 3.2 节给的检查脚本,至少保证语法可编译。更严格的一步是真实执行一次,确认输出和你在 PDF 里写的一致。如果确实依赖第三方库,在代码块上方用一句话说明“需要安装某库”,但不要为了演示去背一堆外部依赖。
4.4 现象:只看不写,面试时手写代码出洋相
八股文 PDF 是静态资料,复习时很容易陷入“眼睛看懂了”的错觉。我见过 A 同学把装饰器原理倒背如流,面试官让他手写一个完整装饰器,他写不出闭包的返回结构。原因就是手写和阅读用的脑区不同,看得懂不代表写得出来。
解决:每周抽 3 个知识点,用文本编辑器打开一个空白文件,不参考 PDF 从头写代码。写完再和 PDF 对照。如果你能用笔在纸上写出def decorator(func): def wrapper(*args, **kwargs): ... return wrapper这样的整体结构,再去面试才稳。另一个实操方案是让朋友帮忙抽题,你直接在白板上写,写完再讲一遍。这个过程痛苦,但比对着 PDF 默读有效得多。
5. 用“一分钟讲题法”把八股文变成面试答案
PDF 整理完,剩下一步是“把知识讲出来”。我试过最有效的方式是“一分钟讲题法”:随机抽一个知识点,给自己一分钟,用三句话说清楚——它是什么、为什么存在、怎么用。拿 GIL 举例,你的三句可以是:
- GIL 是官方解释器里的全局锁,它保证同一时刻只有一个线程在执行 Python 字节码。
- 它的存在是为了保护引用计数和内存管理,避免多线程同时操作对象导致内存错误。
- 所以 CPU 密集任务用多进程绕开 GIL,I/O 密集任务用多线程依然有收益。
这三句话不能照背,要边想边说。我个人的习惯是打开手机录音,讲完回放。如果哪句话出现“呃”“那个”超过两次,说明这个知识点还没形成肌肉记忆。回放时重点听因果连接词:是“因为...所以...”,还是“反正就是这样”。
这个方法也可以用于验证 PDF 里的表述。当你把一分钟录音转成文字,对照 PDF 原文,你会发现很多地方 PDF 用的是书面语,而你说出的是口语。口语才是面试时的表达方式。所以我在整理 PDF 时,会把一些关键条目改成口语化的“我来说一遍”版本。比如装饰器,我会在 PDF 里写:“装饰器就是把一个函数传给另一个函数,内层函数把它包起来,再返回新函数。用@只是省去手动赋值的语法糖。”这句话比“装饰器是一个接受函数并返回新函数的可调用对象”更适合面试现场。
最后分享一个教训:我曾经把整份 PDF 背得滚瓜烂熟,结果面试官让我“解释下with怎么保证文件一定被关闭”,我只说了“因为__exit__会被调用”,没能讲清“就算中途异常,解释器也会保证调用__exit__,把清理推进栈里”。后来我用一分钟讲题法把所有涉及资源释放的知识点重练了一遍,才真正补上这块。整理八股文 PDF 不是终点,把它讲成自己的话才是。希望帮到你。
本文还有配套的精品资源,点击获取