python面试高频易错题核心在于理解语言机制:可变默认参数复用对象、is与==混淆对象身份与值、循环删元素导致索引错位、闭包变量延迟绑定。

Python面试里那些“看着简单、一写就错”的题,核心不在考语法多熟,而在看你是否真正理解语言行为背后的机制。下面挑几个高频又容易栽跟头的点,说清原理和应对方式。
可变对象当默认参数:不是写错了,是理解偏了
典型代码:
def add_item(item, lst=[]):
lst.append(item)
return lst
连续调用两次,第二次结果会带上第一次的元素。这不是 bug,是设计使然:函数定义时,[] 就被创建了一次,之后所有调用都复用这个 list 对象。
立即学习“Python免费学习笔记(深入)”;
- 正确做法:用
None作默认值,进函数再初始化if lst is None: lst = [] - 验证技巧:打印
id(lst),两次调用如果 id 相同,说明是同一个对象 - 延伸理解:不可变对象(如
int、str)没这问题,因为赋值操作会绑定新对象;而append是原地修改
is 和 == 混用:别只背定义,要看运行时对象身份
很多人能说出“is 看地址,== 看值”,但遇到具体例子还是错:
a = 257
b = 257
print(a is b) # 实际输出 False
原因:CPython 对 -5 到 256 的小整数做了缓存,超出范围后每次字面量都会新建对象。所以 257 is 257 在某些上下文(比如单行语句)可能为 True,但不能依赖。
- 原则:判断相等一律用
==;只有检查是否为同一对象时才用is - 安全用法:
if x is None比if x == None更可靠 - 字符串也有类似驻留行为,但受编译器优化影响,跨环境不保证一致
循环中直接删列表元素:索引悄悄错位
常见写法:
for item in lst:
if item % 2 == 0:
lst.remove(item)
如果列表是 [1, 2, 4, 5],删掉 2 后,4 自动前移到索引 1,但 for 循环下一次已指向索引 2(也就是 5),于是 4 被跳过。
- 推荐解法一:列表推导式
lst = [x for x in lst if x % 2 != 0] - 推荐解法二:遍历副本
for item in lst[:]:,冒号切片生成新列表,原列表可安全修改 - 避免反模式:不用
range(len(lst))配合remove,逻辑更绕且易出错
闭包中变量延迟绑定:i 不是你以为的那个 i
典型陷阱代码:
funcs = []
for i in range(3):
def func(): return i
funcs.append(func)
print([f() for f in funcs]) # 输出 [2, 2, 2]
所有函数共享同一个 i 变量,循环结束时 i 值为 2,所以每个函数返回的都是最终值。
- 修复方式:用默认参数捕获当前值
def func(x=i): return x - 或用
functools.partial绑定参数 - 本质是作用域和生命周期问题,不是循环本身的问题










