Python中默认参数的作用域是什么?

34 投票
7 回答
6614 浏览
提问于 2025-04-15 19:43

当你在Python中定义一个带有数组参数的函数时,这个参数的作用范围是什么呢?

这个例子来自Python的教程:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

输出结果是:

[1]
[1, 2]
[1, 2, 3]

我不太确定我是否理解这里发生了什么。这是否意味着数组的作用范围在函数外面?为什么数组在每次调用时都能记住它的值?我之前用过其他语言,通常只有当变量是静态的时,才会有这样的行为。否则,我觉得每次调用时应该会重置。而实际上,当我尝试以下代码时:

def f(a):
    L = []
    L.append(a)
    return L

我得到了我预期的结果(数组在每次调用时被重置)。

所以我觉得我只需要解释一下这一行 def f(a, L=[]): - 变量 L 的作用范围是什么呢?

7 个回答

3

其实这里的“魔法”比你想象的还要少。这相当于

m = []

def f(a, L=m):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

m 只会被创建一次。

7

你对变量 L 的作用范围理解得很对。

其实“问题”出在你用 [] 创建的列表上。Python 在你每次调用这个函数的时候,并不会创建一个新的列表。每次调用时,L 都是指向同一个列表,这就是为什么这个函数会“记住”之前的调用。

所以实际上你得到的是这样的情况:

mylist = []
def f(a, L=mylist):
    L.append(a)
    return L

Python教程是这么说的:

默认值只会被计算一次。当默认值是一个可变对象,比如列表、字典或大多数类的实例时,这一点尤其重要。

它还建议了一种可以实现你期望行为的编码方式:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
28

作用域就像你想的那样。

可能让人惊讶的是,默认值只计算一次,然后重复使用。所以每次你调用这个函数时,得到的都是同一个列表,而不是一个新的空列表。

这个列表存储在 f.__defaults__ 中(在 Python 2 中是 f.func_defaults)。

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)
print f.__defaults__
f.__defaults__ = (['foo'],) # Don't do this!
print f(4)

结果:

[1]
[1, 2]
[1, 2, 3]
([1, 2, 3],)
['foo', 4]

撰写回答