Python:列表作为字典中的键 -

时间:2016-02-04 03:23:44

标签: python list dictionary

我正在尝试读取具有非常相似数据的多个文件。该数据的每一行都有一个accessor_key和一个与之相关的值。我正在尝试创建一个字典,其中accessor_key作为字典键和字典值 - 到目前为止读取的所有值的列表。

我的代码如下所示:

with open(ind_file, "r") as r:
  for line in r:
    nline = line.strip()
    spl = nline.split(",")
    if agg_d.has_key(spl[0]):

      key = spl[0]
      val = spl[1]
      dummy = agg_d[key]
      dummy.append(val)
      agg_d[key] = dummy
      print key, agg_d[key]

    else:
      print "Something is wrong"
      print agg_d
      print spl[0]
      print spl[1]

正如你所看到的,我希望每次都能使值变大,(每次迭代时列表的大小增加1)并将其存储回字典中。 但是,当我运行此程序时,字典中的所有键都采用列表的值。

因此,例如在程序的开头,字典是:

agg_d = {'some_key': [], 'another_key': []}

运行后,它变为:

agg_d = {'some_key': ['1'], 'another_key': ['1']}

应该只是:

agg_d = {'some_key': ['1'], 'another_key': []}
编辑:我找到了我正在寻找的工作。我只是做了:

with open(ind_file, "r") as r:
for line in r:
  nline = line.strip()
  spl = nline.split(",")
  if agg_d.has_key(spl[0]):

    key = spl[0]
    val = spl[1]
    dummy = agg_d[key]
    ad = dummy[:]
    ad.append(val)
    agg_d[key] = ad
    print key, agg_d[key]

  else:
    print "Something is wrong"
    print agg_d
    print spl[0]
    print spl[1]

但我仍然想知道为什么会发生这种情况。 'dummy'是否引用了字典的所有值?我用Python 2.7运行它。

3 个答案:

答案 0 :(得分:2)

  

虚拟'引用字典的所有值?我用Python 2.7运行它。

是。您已添加对列表的引用,并且可能存在对您所观察到的同一列表的多个引用。为了简单说明这一点,试试这个:

dummy = [1,2,3]          # creates a list object and assigns reference to the name 'dummy'
d = dict()
d['some key'] = dummy    # creates the key 'some key' in the dictionary and assigns its value as the reference to the name 'dummy'

dummy.append(4)          # mutates the list referred to by name 'dummy'
                         # at this point, all references to that object have mutated similarly

print d['some key']

您将观察到以下输出:

>>> [1,2,3,4]

您的解决方法没问题,但您可以改进:

with open(ind_file, "r") as r:
    for line in r:
      spl = line.strip().split(",")
      key, val = spl[0], spl[1]
      if key in agg_d:
        agg_d[key] = agg_d[key][:].append(val)
        print key, agg_d[key]
      else:
        print "Something is wrong"
        print agg_d
        print spl[0]
        print spl[1]

agg_d[key] = agg_d[key][:].append(val)

这不会改变你的dummy列表,并将值重新分配给字典。同时避免使用一些不必要的变量,例如nlinead以及dummy

答案 1 :(得分:1)

看起来agg_d已经使用您预期的密钥初始化了。你没有说明这是如何完成的,但我猜测所有的初始值实际上都是相同的列表 - 你在上面的代码中追加了值。

如果您使用每个键的新列表初始化agg_d,则问题应该消失。你可以用词典理解来做到这一点:

>>> keys = ["a", "b", "c"]
>>> agg_d = {k:[] for k in keys}
>>> agg_d["a"].append(1)
>>> agg_d
{'a': [1], 'c': [], 'b': []}

或者,根据您的需要,您可以在阅读文件时遇到每个密钥时按需初始化每个条目。

您的解决方法有效,因为它用新列表替换原始列表并删除共享引用。

答案 2 :(得分:0)

问题在于,默认情况下,Python只是将列表的引用添加为dict值,而不是列表本身。所以dict值实际上是指向同一个对象的一堆指针。您需要使用您在comment中建议的dummy [:]或copy.deepcopy()更明确地复制列表。