一段奇怪的Python代码,ChatGPT的解释——Python默认参数的可变对象共享

def foo(a, b=[]):
     b.append(a)
     return b
 ​
 print(foo(1))
 print(foo(1))
 print(foo(1))

 

这段代码会产生许多人可能意料之外的结果。以下是代码的行为以及背后的原因:

代码行为

def foo(a, b=[]):  # 默认参数 b 是一个空列表
    b.append(a)    # 将 a 添加到 b
    return b

print(foo(1))  # 第一次调用
print(foo(1))  # 第二次调用
print(foo(1))  # 第三次调用

输出

[1]
[1, 1]
[1, 1, 1]

原因

  1. 默认参数的可变对象共享

    • 在 Python 中,默认参数只在函数定义时被评估一次。如果默认参数是一个可变对象(如列表或字典),它会在所有后续的函数调用中被共享。
    • 因此,每次调用 foo 时,如果未显式传递参数 b,它会继续使用同一个 b(即最初创建的那个空列表)。
  2. b 是同一个对象

    • 每次调用 foo(1) 时,b.append(a) 会将值添加到同一个共享列表中,而不是重新创建一个新的列表。

如何修复

如果希望每次调用 foo 时都使用一个新的空列表,可以将默认参数设置为 None,并在函数内部进行处理:

def foo(a, b=None):
    if b is None:  # 检查 b 是否为 None
        b = []     # 创建一个新的列表
    b.append(a)
    return b

print(foo(1))  # 输出: [1]
print(foo(1))  # 输出: [1]
print(foo(1))  # 输出: [1]

修复后的输出

[1]
[1]
[1]

总结

  • 默认参数的可变对象(如列表或字典)会被所有调用共享,导致意外的累积效果。
  • 解决方法是使用不可变的默认值(如 None),并在函数内部显式创建新的对象。
posted @ 2024-12-03 16:02  Abraham_Xu  阅读(6)  评论(0编辑  收藏  举报