python三大常见陷阱:可变默认参数导致对象复用;浅拷贝不复制嵌套对象引用;闭包后期绑定致循环变量值错误;is仅应用于none/布尔判断,其余用==。

可变对象作为函数默认参数
这是Python面试中最高频的陷阱之一。很多人误以为每次调用函数时,默认参数都会重新初始化,但实际上,默认参数在函数定义时只被创建一次,且对可变对象(如list、dict)来说,多次调用会持续复用同一个对象。
例如:
def add_item(item, lst=[]):
lst.append(item)
return lst
<p>print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 意外!不是[2]正确写法是用None作占位符,在函数体内初始化:
- 用 lst=None 代替 lst=[]
- 在函数开头加判断:if lst is None: lst = []
浅拷贝与深拷贝混淆
面试常问“a = [[1,2], [3,4]]; b = a.copy();修改b[0][0]会影响a吗?”答案是:会。因为copy()和:切片都只做浅拷贝,嵌套的子对象仍是同一引用。
立即学习“Python免费学习笔记(深入)”;
关键区别:
- 浅拷贝:只复制最外层容器,内部可变对象仍共享
-
深拷贝:递归复制所有层级,完全独立(用
import copy; copy.deepcopy())
注意:不可变对象(str、int、tuple)无论深浅拷贝都安全,问题集中在list/dict/set等嵌套结构上。
闭包中变量绑定延迟求值
写循环生成多个lambda或函数时,容易忽略Python的后期绑定(late binding)机制:闭包中引用的变量,是在内层函数被调用时才去读取当前值,而非定义时。
典型错误代码:
funcs = []
for i in range(3):
funcs.append(lambda: i)
print([f() for f in funcs]) # 输出 [2, 2, 2],不是 [0, 1, 2]修复方式(任选其一):
- 用默认参数捕获当前值:lambda x=i: x
- 用闭包函数封装:lambda: i 改为 (lambda x: lambda: x)(i)
- 改用列表推导式(自带作用域隔离):[lambda x=i: x for i in range(3)]
is 和 == 的误用
很多候选人把 is 当作“等于”来用,尤其在判断 None、布尔值或小整数时侥幸成功,但这是危险的依赖实现细节的行为。
根本区别:
-
== 比较的是两个对象的值是否相等(调用
__eq__) - is 比较的是两个变量是否指向同一内存地址(即是否为同一个对象)
可靠用法只有:obj is None、flag is True/False(推荐直接用 if obj: 或 if not obj: 更Pythonic)。其他场景一律用 ==。










