首页 > 解决方案 > 具有默认值的 Python defaultdict 类实例化

问题描述

当 defaultdict 配置为实例化一个类时,如果该类具有默认参数,则行为会有所不同。

例如,这是预期的行为:

from typing import List
from collections import defaultdict

class Test:
    def __init__(self):
        self.values = []

tests = defaultdict(Test)

tests['a'].values.append(1)
tests['b'].values.append(2)

print([f"{id}: {t.values}" for id, t in tests.items()]) #--> ['a: [1]', 'b: [2]']

现在,当类具有默认值时,所有对象共享相同的引用:

class Test:
    def __init__(self, values = []):
        self.values = values

tests = defaultdict(Test)

tests['a'].values.append(1)
tests['b'].values.append(2)

print([f"{id}: {t.values}" for id, t in tests.items()]) #--> ['a: [1, 2]', 'b: [1, 2]']

仅当参数是引用时才会发生这种情况,例如:

class Test:
    def __init__(self, values = 0):
        self.values = values

tests = defaultdict(Test)

tests['a'].values += 1
tests['b'].values += 1

print([f"{id}: {t.values}" for id, t in tests.items()]) #--> ['a: 1', 'b: 1']

这是为什么?

标签: pythonclassinstantiationdefaultdict

解决方案


发生这种情况是因为在定义函数时会精确评估一次默认值,而不是每次调用它时。

https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments

为了澄清,python中的所有变量都是引用。只是他们所指的有些东西是可变的,有些则不是。


推荐阅读