共享默认列表
容易留下上次痕迹def add_student(name, roster=[]):
roster.append(name)
return roster
本次调用帧
name → 小满roster → 默认对象 D0
→
定义时创建的对象
D0 · 一直被函数保存
目前还是空列表 []
调用记录
- 尚未调用
最容易误会的一句话是“没传列表,就给我一个空列表”。真正发生的是:函数定义执行时先做出一个列表,以后没传实参的调用都回到它这里。
def add_student(name, roster=[]):
roster.append(name)
return roster
def add_student(name, roster=None):
if roster is None:
roster = []
roster.append(name)
return roster
默认值表达式跟着 def 在定义阶段求值,不会等到每次调用再求值。数字和字符串同样只求值一次,只是它们不可变,通常看不出“共用”带来的副作用。
append 改的是列表本身;下次调用再次见到同一个列表。如果显式传入自己的列表 team = [],再执行 add_student("小满", team),会改到哪里?
None 当哨兵,并在函数体内创建;需要有意共享缓存时,才保留可变默认值,而且要把这个行为写清楚。