Python:字典作为实例变量

21 投票
2 回答
17217 浏览
提问于 2025-04-16 17:45

可能重复的问题:
Python中的“最小惊讶”:可变的默认参数

我对Python 3中字典作为类实例变量的行为感到很困惑。我的理解是,Python中的实例变量是针对每个实例单独存储的,而类变量是针对整个类的(这和其他一些语言中的“静态”变量类似)。

这种理解似乎是正确的,但当实例变量是一个从默认参数创建的字典时,就出现了问题。例如:

class Foo:
    def __init__(self, values = dict()):
        self.values = values

f1 = Foo()
f1.values["hello"] = "world"

f2 = Foo()
print(f2.values)

这个程序的输出是:

{'hello': 'world'}

咦?为什么实例 f2f1 有相同的字典实例呢?

如果我不传递一个空字典作为默认参数,而是明确地将 self.values 赋值为一个空字典,我就能看到预期的行为:

class Foo:
    def __init__(self):
        self.values = dict()

但我不明白为什么这样会有任何区别。

2 个回答

3

默认值只会被计算一次。如果你想要的效果是这样的:

 class Foo:
     def __init__(self, values = None):
         self.values = values or dict()

如果你提供了一个 values,那么这个值会被使用。如果没有提供,values 会被 or 操作符当作 FALSE 来处理,这样就会创建一个新的字典。

19

这是Python中一个大家都知道的惊喜。默认参数是在函数定义的时候就被计算出来的,而不是在函数被调用的时候。所以你的默认参数其实是指向一个公共的dict。这和把它赋值给类或实例变量没有关系。

如果你想使用默认参数,建议用None,然后再进行检查:

if values is None:
    self.values = {}
else:
    self.values = values

撰写回答