python - 为什么二级字典的值在 Python 2.7 中都指向同一个对象?

标签 python list python-2.7 dictionary append

我试图定义一个函数来创建一个两层字典,所以它应该产生格式

dict = {tier1:{tier2:value}}.

代码是:

def two_tier_dict_init(tier1,tier2,value):
    dict_name = {}
    for t1 in tier1:
        dict_name[t1] = {}
        for t2 in tier2:
            dict_name[t1][t2] = value
    return dict_name

所以下面的例子...

tier1 = ["foo","bar"]
tier2 = ["x","y"]
value = []
foobar_dict = two_tier_dict_init(tier1,tier2,value)

从表面上看,它产生了我想要的:

foobar_dict =  {'foo':{'x': [],'y':[]},
                'bar':{'x': [],'y':[]}}                   }

但是,当 append 任何值时

foobar_dict["foo"]["x"].append("thing")

所有值都被追加,因此结果是:

foobar_dict =  {'foo':{'x': ["thing"],'y':["thing"]},
                'bar':{'x': ["thing"],'y':["thing"]}}

起初我假设由于我的定义构建字典的方式,所有值都指向内存中的相同空间,但我无法弄清楚为什么会这样。然后我发现,如果我将值从空列表更改为整数,当我执行以下操作时,

foobar_dict["foo"]["x"] +=1

仅更改所需的值。

因此我必须得出结论,它与 list.append 方法有关,但我无法弄清楚。什么解释?

注意我需要此功能来构建大型词典,其中每一层都有数百个元素。我也用同样的方法构建了一个三层版本,出现了同样的问题。

最佳答案

您只传入了一个列表对象,而您的第二层字典只存储了对该对象的引用。

如果您需要存储不同的列表,则需要为每个条目创建一个新列表。您可以为此使用工厂函数:

def two_tier_dict_init(tier1, tier2, value_factory):
    dict_name = {}
    for t1 in tier1:
        dict_name[t1] = {}
        for t2 in tier2:
            dict_name[t1][t2] = value_factory()
    return dict_name

然后使用:

two_tier_dict_init(tier1, tier2, list)

让它创建空列表。如果您想存储不可变对象(immutable对象)(如字符串或整数),您可以在此处为值工厂使用任何可调用对象,包括 lambda:

two_tier_dict_init(tier1, tier2, lambda: "I am shared but immutable")

您可以使用字典理解来简化您的函数:

def two_tier_dict_init(tier1, tier2, value_factory):
    return {t1: {t2: value_factory() for t2 in tier2} for t1 in tier1}

关于python - 为什么二级字典的值在 Python 2.7 中都指向同一个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21433070/

相关文章:

python - 如何使用Python从dict中提取具有特定模式的键列表?

python - Django Rest Framework 不像标准 POST 请求那样解码 Multipart 请求中的 JSON 字段

Python 引用旧的 SSL 版本

python - 使用 Highcharts 的 Django Chart

python - 将循环变成列表 python

python - 有没有一种简单的方法可以借助numpy获得正态分布的概率密度?

python - str.__getslice__ 没有按预期工作,负停止

python - 自动补零数组

python - 使用列表中的 max()/min() 获取返回的最大或最小项的索引

c++ - 在列表 vector 中的单个/多个列表中添加元素