简介面向Python后端岗位求职者的大厂面试题手册内容覆盖阿里、腾讯、百度、华为、字节、网易、美团等多家互联网公司的高频考点。整份资料为23页PDF以Python语言特性、操作系统、数据库、计算机网络、编程题为主线几乎涵盖后端面试中常见的知识模块。资源仅含1个PDF文件体积1.1MB轻巧便携适合在通勤或碎片时间快速过一遍重点。已有219人参与学习。具体内容包括Python参数传递、元类、类方法/静态方法、生成器与迭代器、GIL、协程、垃圾回收以及操作系统里的调度算法、死锁、虚拟内存数据库中的事务、索引、Redis原理、乐观锁/悲观锁、MVCC网络部分的三次握手、四次挥手、HTTP/HTTPS、Cookie与Session等同时附录了台阶问题、快排、动态规划等编程题及解答。对准备大厂Python后端面试的候选人来说这是一份能快速回忆核心知识点的浓缩手册。1. 一份23页面试题真正该背的是什么背完23页PDF面试官一句“你再说细一点”就能把人卡在原地。很多Python后端开发者把面试题当八股文处理刷一遍记住答案就上场结果面试官从“装饰器是什么”追问到“函数定义时发生了什么”立刻露馅。实际上“BAT大厂互联网面试题”这份材料只是索引真正有价值的是把每个问题拆成原理、代码和参数。后端面试八股文最大的坑就是把问题背成孤立答案一旦追问就断片。对准备大厂后端岗位的人来说这份面试题需要按“语言基础、后端工程、项目表达”三层重新组织。本文就围绕这份23页面试题从Python语言核心讲到数据库、缓存与消息队列最后落成一套可复现的复习方法适合准备校招或社招的Python后端开发者也适合工作三五年的老手查漏补缺。2. Python语言核心考点从语法题看到底层实现面试题里占比最大的往往是Python语言基础。很多人觉得这些问题太简单但恰恰是这些题能区分“用过Python”和“理解Python”两种人。这里从四类高频问题展开每个都能继续往下追问。2.1 可变与不可变对象一道题能问出五个结果面试题里常见的问法是“和is的区别是什么”。标准回答是比较值is比较地址。但真正的考点在后面Python对小数和整数的驻留、字符串复用、list与tuple的可变性差异。面试官听完第一句马上会接着问“那赋值复制的是值还是引用”。a [1, 2, 3] b a c [1, 2, 3] print(a is b) # Trueb只是a的别名 print(a is c) # Falsec是新对象 print(a c) # True值相同这段代码说明is比较的是内存地址比较的是值。a和b指向同一块内存所以is为Truea和c虽然内容相同但各自维护一块内存所以is为False。继续追问时面试官会问列表和元组的差别或者“函数参数是按值还是按引用”。实际Python传参既不是纯按值也不是纯按引用而是传对象引用最终行为取决于对象是否可变。下面这张表能帮助快速回忆。对象类型可变性常见坑int, float, str, tuple不可变拼接字符串产生新对象list, dict, set, bytearray可变默认参数引用同一个列表frozenset不可变不能作为字典键默认参数绑定发生在函数定义时所以列表默认参数会被后续所有调用共享这个坑在真实项目里导致过多次数据串号。面试时可以主动举这个反例说明你理解函数对象和可变对象的关系而不是只会背“默认参数必须不可变”。2.2 GIL与多线程别只说“有锁”第二类高频题围绕GIL展开。常见问法是“Python多线程是不是伪线程”或者“如何提升Python并发性能”。对五年以上经验的开发者面试官希望听到你对全局解释器锁本质的说明GIL是一把CPython解释器级的互斥锁它保证同一时刻只有一个线程执行Python字节码。import threading import time def busy_calc(): for _ in range(5_000_000): _ 1 1 start time.time() threads [threading.Thread(targetbusy_calc) for _ in range(4)] for t in threads: t.start() for t in threads: t.join() print(4线程耗时:, time.time() - start)这段代码是CPU密集型场景。4个线程跑满也不会有明显加速原因是GIL让计算任务只能占用一个核心。如果换成IO密集任务比如请求外部接口线程在等待期间会释放GIL多线程就能有效缩短总耗时。对比下来可以按场景收敛。场景推荐方案原理CPU密集多进程、C扩展每个进程有独立解释器和GILIO密集多线程、协程等待期间让出GIL高并发网络服务协程加异步框架单线程事件循环避开锁竞争在回答完这些之后可以补一句新版Python已经尝试提供不带GIL的实验性构建但主流线上版本仍是CPython默认GIL。这句话能体现你关注语言演进而不是只背面经。面试前把Python环境装到常用版本再开始刷题避免在不同版本行为差异上浪费复习时间。2.3 装饰器、生成器与内存优化装饰器和生成器几乎是必考题。装饰器考察函数对象和闭包生成器考察惰性计算。一道题能带出三四个追问点。from functools import wraps import time def cost_time(func): wraps(func) def wrapper(*args, **kwargs): start time.time() result func(*args, **kwargs) print(f{func.__name__} cost {time.time() - start:.4f}s) return result return wrapper cost_time def parse_data(n100000): return sum(i for i in range(n))wraps的作用是把原函数的__name__和__doc__复制到wrapper上否则调试时所有被装饰的函数都显示为wrapper。面试官喜欢追问装饰器在函数定义时执行还是调用时执行答案是在定义时执行装饰器工厂真正执行wrapper内部逻辑是在调用parse_data时。生成器是另一个经典考点。读取大日志文件时直接整个读入内存会导致内存膨胀def read_big_log(path): with open(path, r, encodingutf-8) as f: for line in f: yield line.strip()这段代码逐行读取并按需产出内容内存占用只取决于单行长度而不是整个文件大小。遇到“内存占用怎么排查”时生成器加tracemalloc是常用的组合回答能指出具体哪段代码在累积数据比只说“用内存分析工具”更具操作感。2.4 深浅拷贝一个例子说清内存模型深浅拷贝题也经常出现在Python语言部分。它的价值在于考察对象之间如何共享内存以及如何避免意外修改。import copy original {items: [1, 2], name: cache} shallow copy.copy(original) deep copy.deepcopy(original) shallow[items].append(3) print(original[items]) # [1, 2, 3]浅拷贝共享内层列表 print(deep[items]) # [1, 2]深拷贝完全独立copy.copy只复制外层容器字典里的列表还是同一个对象copy.deepcopy会递归复制所有嵌套对象。面试题常给出一个字典嵌套列表的图问复制后修改是否互相影响。回答要点是浅拷贝适合结构简单、不嵌套可变对象的场景深拷贝代价更高但对数据隔离更可靠。项目里保存配置快照时用深拷贝缓存对象直接引用时用浅拷贝。3. 后端工程题数据库、缓存、消息队列与网络Python语言题之后大厂面试题的后半段几乎全是后端工程问题。这里的核心不是背概念而是把问题和线上故障排查经验挂钩。没有真实故障经历也要用可运行的命令和参数来说明。3.1 MySQL索引与慢查询别只背B树几乎所有后端面试都会出现“为什么MySQL用B树做索引”。但面试官还会继续追联合索引和最左前缀原则再落到慢查询优化。只答聚簇索引和非聚簇索引的区别已经不够要给出具体操作。EXPLAIN SELECT order_id, user_id, amount FROM orders WHERE user_id 1024 AND status 1 ORDER BY create_time DESC;EXPLAIN是慢查询分析的第一步。重点看type、key、rows三个字段。type出现ALL说明全表扫描key为NULL说明没走索引rows数字越大越危险。针对这条语句可以设计一个联合索引ALTER TABLE orders ADD INDEX idx_user_status_time (user_id, status, create_time);联合索引最左前缀原则在这里的体现是where里的user_id和status用到了联合索引create_time也能利用索引的有序性避免filesort。实际落地时要注意区分度status这种低区分度字段放中间位置避免索引失效。线上如果开启慢查询日志可以这样确认当前配置。mysql -uroot -p -e SHOW VARIABLES LIKE slow_query_log%;在会话里执行 set global long_query_time 1生产环境则要写入my.cnf再重启。排查Linux服务器问题时如果数据库连接数过高用netstat加grep统计TIME_WAIT数量这类Linux面试题也常出现在大厂二面里。3.2 Redis缓存穿透、击穿与雪崩参数与代码层面怎么防Redis面试题在23页面试题里几乎必有而且喜欢把三个概念放在一起考穿透、击穿、雪崩。三者分别对应查询不存在的数据、热点key过期、大量key同时过期。解决方案不止是讲概念要落到参数和代码。import redis import time pool redis.ConnectionPool( host127.0.0.1, port6379, db0, max_connections50, socket_timeout3 ) r redis.Redis(connection_poolpool) def get_order(order_id): cache_key forder:{order_id} cached r.get(cache_key) if cached: return cached value load_from_db(order_id) if value is None: # 缓存空值防止穿透 r.setex(cache_key, 60, ) return None # 加随机过期时间防止雪崩 expire 300 int(time.time() % 30) r.setex(cache_key, expire, value) return value查询数据库之前先查缓存命中则直接返回数据库不存在时缓存空值一分钟拦截恶意请求反复打库。防止雪崩的关键是过期时间不固定这里用时间戳对30取模加随机偏移。对于热点key即将过期但还没过期时的并发击穿常见做法是加互斥锁重建缓存。下面这张表把三种情况的区分和应对列在一起。问题现象常见应对穿透请求不存在的keyDB被打布隆过滤器、缓存空值击穿单个热点key失效互斥锁重建、热点不设过期雪崩大量key同时失效过期时间加随机值、多级缓存参数说明要与场景挂钩max_connections控制连接池上限设置太大会拖垮Redis实例太小会阻塞请求socket_timeout设3秒避免Redis假死时请求无限等待。这两个参数写进简历里比“熟悉Redis”更有说服力。3.3 消息队列与Celery异步任务后端解耦的常见选型“你们项目里为什么用消息队列”几乎是必问题。答案不只是“削峰填谷”还要说出选型理由和落地配置。Python后端常用的异步方案是Celery配合RabbitMQ或Redis。CELERY_BROKER_URL amqp://guest:guestlocalhost:5672// CELERY_RESULT_BACKEND redis://localhost:6379/1 CELERY_TASK_SERIALIZER json CELERY_TIMEZONE Asia/Shanghaibroker_url是任务发往的队列地址result_backend是任务结果写回的地方也就是热搜词里常说的celery结果存储后端。选型时主要看吞吐要求Kafka适合日志收集和事件流RabbitMQ适合复杂路由和可靠投递。回答时不要说哪个更好而是给结论“订单超时取消这种需要可靠确认的场景我选RabbitMQ用户行为日志采集压到Kafka。”这样更有工程感。后端跨域也是高频追问点尤其在前后端分离项目实战里。CORS本质是浏览器的同源策略后端解决方式是增加响应头。用Flask框架时常见的写法是app.after_request def add_cors_headers(response): response.headers[Access-Control-Allow-Origin] * response.headers[Access-Control-Allow-Methods] GET, POST, OPTIONS return response生产环境不能把Access-Control-Allow-Origin直接写成星号需要限定业务域名。这里可以自然聊到Nginx反向代理时的add_header设置表现你对前后端整个链路的理解。4. 把23页面试题变成一套可复现的复习系统单纯背诵会导致接不住追问。更有效的做法是把手里的PDF整理成自己的题库每道题都带答案、代码和项目印证。这个系统一旦建立也能复用到Java、前端等其他岗位的面试准备中。4.1 给面试题分类按考点打标签拿到23页面试题先做分类而不是阅读。以“Redis为什么快”这道题为例建立如下卡片模板## 问题Redis为什么快 - 标签Redis / IO多路复用 / 性能 - 答案要点纯内存操作、单线程避免锁竞争、epoll事件驱动 - 手写片段setex / getset 命令 - 追问点单线程如何利用多核CPU - 项目印证用户会话缓存、热点商品计数把每道题拆成五个部分答案要点控制在三行以内手写片段必须能在本地运行。完成分类后高频考点会自然浮出水面比如数据库和Redis类别的题目数量会明显多于环境搭建类。这一步的意义是让复习顺序不再跟随PDF目录而是跟随薄弱项。4.2 把答案变成可执行的断言复习时最怕“看懂了但写不出来”。解决方法是把答案改写成可运行验证的pytest用例。以幂等接口这类后端题为例import pytest def create_order_if_absent(order_id): if order_id in create_record: return False create_record.add(order_id) return True create_record set() def test_idempotent(): assert create_order_if_absent(order_001) is True assert create_order_if_absent(order_001) is False代码逻辑是第一次创建订单返回True第二次相同请求返回False证明接口对同一请求号只处理一次。真实场景会结合唯一索引或Redis的setnx但这里把答案变成断言之后复习时就多了一层“代码能跑通”的信心。工程上这叫用测试驱动复习比重复翻PDF更有效。4.3 随机抽题与复习计划建立题库之后还需要一个日常动作保持对题目的反应速度。用简单脚本从json里随机抽题抽中后先自己回答再看答案。import json import random with open(questions.json, r, encodingutf-8) as f: questions json.load(f) for _ in range(5): q random.choice(questions) print(题目:, q[question]) input(按回车查看答案) print(答案:, q[answer])json里的每条记录对应4.1的卡片字段question和answer是必填字段。随机抽取5道题可以在睡前过一遍时间控制在十五分钟以内。如果连续三次抽中同一条题把priority标记为0第二天优先复习。优先级表格可以这样设计。优先级含义复习频率T0高频考点且不熟练每天T1中频考点每两天T2低频但需了解每周一次这套方法同样适用于Java后端完整成长路线或前端面试题2026分类和抽题的颗粒度不变变的只有题库内容。整体投入约一小时建立题库却能长期避免“刷完就忘”的问题。5. 手写算法题的边界自查把不会的题变成加分项面试题PDF的后半部分通常出现算法题比如二分查找、链表反转、LRU缓存。这些题光写主流程不够真正区分水平的是对边界条件的处理。一个具体可用的技巧是写完后立即用三类用例自查——空输入、单元素、目标不存在。def binary_search(arr, target): left, right 0, len(arr) - 1 while left right: mid (left right) // 2 if arr[mid] target: return mid elif arr[mid] target: left mid 1 else: right mid - 1 return -1 test_cases [ ([], 5, -1), ([1], 1, 0), ([1, 2, 3, 4], 5, -1), ([1, 2, 3, 4], 4, 3), ] for arr, target, expected in test_cases: assert binary_search(arr, target) expected四个测试用例分别覆盖空数组、单元素、目标不存在和目标在末尾。确定性的自查步骤是先看循环条件里的等于号再看mid的计算是否溢出最后确认退出时left和right的位置。Python里(left right) // 2在极端长度下没有风险但换成C系语言就要写成left (right - left) // 2。这个技巧可以扩展到所有手写题链表题用空链表和单节点开头动态规划题用n0和n1收尾栈和队列用“空结构执行操作”来测试。把23页面试题里每一道手写题都配上这三类边界用例现场写完后把test_cases逐一报给面试官能直观展示边界处理能力这是单凭背题练不出来的差异点。本文还有配套的精品资源点击获取