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 的速查表:默认参数

  • 安全的默认值: NoneTrueFalse0""(不可变对象)
  • 危险的默认值: []{}set()(可变对象)

问题: 默认参数在定义时 只会被求值一次

解决方案: 使用 None 作为默认值,并在函数体内部初始化可变对象。

调试技巧: 检查 my_function.__defaults__ 以发现隐藏的共享状态。

0 浏览
Back to Blog

相关文章

阅读更多 »

按组反转数组

问题描述:将数组按给定大小 k 分组后逆序。数组被划分为长度为 k 的连续块(窗口),每个块都被逆序。