上周帮朋友调一个Python小脚本,现象很怪:函数明明只在本次调用里往列表append了一条数据,打印出来却带着上一次的旧值。我第一反应是数据没清空,查了一圈,变量都是局部作用域,没道理串。
后来逐行捋,才发现问题出在函数签名上:def f(items=[])。Python的默认参数是在函数定义时创建一次,之后每次调用复用的都是同一个对象。你往里头append,等于在所有人共享的那个列表上做手脚。第一次调用写进去的东西,第二次调用原封不动地还在那儿躺着。文档里其实白纸黑字写着这条,只是大多数人包括我,初学时都扫一眼就翻过去了。
正确做法也简单:默认值写成None,进函数体里判断一下,是None就新建一个空列表。或者干脆用元组这类不可变对象当默认值,从根上断了这个念想。
这事给我的教训是,语言的坑往往不在语法多复杂,而在它执行时机和你直觉不一致。定义时和调用时,一字之差,行为天差地别。各位还踩过哪些"文档里写了但我没看见"的坑,欢迎交流。