Python:字典作为实例变量

Python:字典作为实例变量,python,class,dictionary,python-3.x,Python,Class,Dictionary,Python 3.x,可能重复: 我对Python 3中字典作为类实例变量的行为感到非常困惑。按照我的理解,Python中的实例变量具有每个实例的存储,不同于每个类的类变量(类似于其他一些语言所称的“静态”) 这似乎是正确的,除非实例变量是从默认参数创建的字典。例如: class Foo: def __init__(self, values = dict()): self.values = values f1 = Foo() f1.values["hello"] = "world" f2

可能重复:

我对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'}
嗯?为什么实例
f2
f1
具有相同的字典实例

如果我没有将空字典作为默认参数传入,而只是显式地将
self.values
分配给空字典,则会得到预期的行为:

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

但是我不明白为什么这会有什么不同。

这是Python中一个众所周知的惊喜。默认参数在定义函数时计算,而不是在调用函数时计算。因此,默认参数是对公共
dict
的引用。它与将其分配给类/实例变量无关

如果要使用默认参数,请使用
None
,然后选中它:

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

默认值只计算一次。你想要这样的东西:

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

如果您提供了一个
,则将使用该值。如果不是,则
运算符将
计算为
FALSE
,并实例化一个新的dict。

在加载类时,默认参数可能只计算一次。这样,您只需将相同的引用指定为默认参数。下面是Python标签的常见问题解答:问题4回答了您的问题。列表中的行为与每个可变对象中的行为相同。如果有任何错误作为值传递,例如自定义
dict
子类的空实例,则此操作失败。