Python的秘密生活:默认陷阱
发布: (2026年2月27日 GMT+8 13:37)
2 分钟阅读
原文: Dev.to
Source: Dev.to
为什么永远不应该在默认参数中使用空列表。
🎧 音频版: 想听吗?在 YouTube 上查看此深度解析的 AI 播客扩展版。
📺 视频版: 想看吗?在 YouTube 上查看 7 分钟的可视化解释。
共享内存
def add_student(name, student_list=[]):
student_list.append(name)
return student_list
# First call
print(add_student("Alex"))
# Second call
print(add_student("Alice"))
第二次调用返回 ['Alex', 'Alice'],因为默认列表在函数定义时 只创建一次,而不是每次调用时重新创建。
观察 “僵尸” 变量
你可以通过 __defaults__ 属性检查存储的默认值:
print(f"Before: {add_student.__defaults__}")
add_student("Alex")
print(f"After: {add_student.__defaults__}")
输出
Before: ([],)
After: (['Alex'],)
列表被附加在函数对象上,并在调用之间保持。这种行为仅在 可变 默认值(例如列表、字典)时出现。不可变的默认值如 None、字符串或整数是安全的,因为它们不能被修改。
专业标准
推荐的模式是使用 None 作为哨兵,并在函数内部创建一个新列表:
def add_student(name, student_list=None):
if student_list is None:
student_list = []
student_list.append(name)
return student_list
现在,当没有显式提供列表时,每次调用都会创建一个全新的列表。
Margaret 的速查表:默认参数
- 安全的默认值:
None、True、False、0、""(不可变对象) - 危险的默认值:
[]、{}、set()(可变对象)
问题: 默认参数在定义时 只会被求值一次。
解决方案: 使用 None 作为默认值,并在函数体内部初始化可变对象。
调试技巧: 检查 my_function.__defaults__ 以发现隐藏的共享状态。