前几天帮人排查代码,撞上个特别典型的坑。对方写了个函数大概长这样:def add(x, buf=[]): buf.append(x); return buf。本意是每次调用都从干净的新列表起步,结果第一次 add(1) 返回 [1],紧接着 add(2) 居然吐出 [1, 2]。
根子在于 Python 的默认参数是在函数定义那一刻求一次值的,那个空列表跟后面所有调用共用同一份引用。你 append 进去的东西就赖在那儿不走了,下次调用照单全收。这种 bug 最磨人的地方是它不总是显形,单测里若巧合同一个实例反复用,表现还正常,一上生产环境多调用穿插就乱套,复现都费劲。
正经写法是用 None 占位,进函数体再判断:def add(x, buf=None): if buf is None: buf = []。语义最清楚,调用方想传自己的列表也行,不传就拿全新的。说白了就是得把"定义时"和"调用时"分明白。这坑拿来给刚入门的同学讲求值时机,倒是挺顺手的例子。