如何避免Python中词典列表中的多个更新?

时间:2011-03-20 22:32:59

标签: python dictionary

我有一个包含5个词典的列表,当我更新dictionary[0]时,它还会同时更新dictionary[4]。奇怪的是它不是系统的,字典似乎对我来说是独立的,尽管它们共享相同的内容。

程序1显示我遇到的问题。

程序2显示了使用deepcopy解决方法,但我觉得它不那么聪明。

我想:

  • 了解程序1无法按预期方式运作的原因
  • 是否有更好(更聪明,更有效)的方式来编写程序2.

提前感谢任何反馈。

程序1和程序2更新列表outputDictL中的词典。使用refLists中的数据执行更新。 outputDictL[0]是一个字典,其中包含来自数据的键值。 outputDict[4]是一个字典,其中包含一个字典,其键值在我们的示例中与outputDict[0]相同。

计划1和计划2几乎相同。不同之处在于,在程序2中,我使用字典的深层副本作为函数参数,而不是它的引用。

计划1

程序1源代码:

#!/usr/bin/python
# -*- coding: ISO-8859-15 -*-
# Id: $
L1 = "   "
import copy
##A dds one qTime item to a dictionary
# dates is an array
def addQTime2dict(dictionary, key, dates):
   #"%s       k %s, v: %s"%(L6, key, value)
   print "%s adding key : %s dates : %s"%(L1, key, dates)
   if key in dictionary :
      dictionary[key].extend(dates)
   else :
      dictionary.update({key : dates})

## updates all dictionaries
def updateDicts(outputDictL, S, D, fqdn, dates):
   print "--- fqdn : %s, dates : %s"%(fqdn, dates)
   print "- Before updating Dict[0]\n%s outputDictL : %s"%(L1, outputDictL)
   addQTime2dict(outputDictL[0], fqdn, dates)
   print "- After updating Dict[0]\n%s outputDictL : %s"%(L1, outputDictL)
   if D not in outputDictL[4] :
      outputDictL[4][D] = {}
   print "- Before updating Dict[4]\n%s outputDictL : %s"%(L1, outputDictL)
   addQTime2dict(outputDictL[4][D], fqdn, dates)
   print "- After updating Dict[4]\n%s outputDictL : %s"%(L1, outputDictL)
outputDictL = map( lambda x : {} , range(5))

refList = [("S1", "D1", "f1", "data1"), ("S2", "D1", "f1", "data2")]

for l in refList :
   print "-------------------"
   updateDicts(outputDictL, l[0], l[1], l[2], [l[3]])
   print "-------------------\n"

程序1输出:

-------------------
--- fqdn : f1, dates : ['data1']
- Before updating Dict[0]
    outputDictL : [{}, {}, {}, {}, {}]
    adding key : f1 dates : ['data1']
- After updating Dict[0]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {}]
- Before updating Dict[4]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {}}]
    adding key : f1 dates : ['data1']
- After updating Dict[4]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
-------------------

这正如我们所料。 f1,data1正确放置在outputDictL[0]outputDictL[4]

-------------------
--- fqdn : f1, dates : ['data2']
- Before updating Dict[0]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
    adding key : f1 dates : ['data2']
- After updating Dict[0]
    outputDictL : [{'f1': ['data1', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1', 'data2']}}]
- Before updating Dict[4]
    outputDictL : [{'f1': ['data1', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1', 'data2']}}]
    adding key : f1 dates : ['data2']
- After updating Dict[4]
    outputDictL : [{'f1': ['data1', 'data2', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1', 'data2', 'data2']}}]
-------------------

这不是我们的预期:每次更新这些词典时,f1:data2已插入outputDictL[0]outputDictL[4]。要查看我们的期望,您可以查看Program2输出。

计划2

程序2源代码:

#!/usr/bin/python
# -*- coding: ISO-8859-15 -*-
# Id: $ 
L1 = "   "
import copy
##A dds one qTime item to a dictionary
# dates is an array
def addQTime2dict(dictionary, key, dates):
   #"%s       k %s, v: %s"%(L6, key, value)
   print "%s adding key : %s dates : %s"%(L1, key, dates)
   if key in dictionary :
      dictionary[key].extend(dates)
   else :
      dictionary.update({key : dates})
   return dictionary

## updates all dictionaries
def updateDicts(outputDictL, S, D, fqdn, dates):
   print "--- fqdn : %s, dates : %s"%(fqdn, dates)
   print "- Before updating Dict[0]\n%s outputDictL : %s"%(L1, outputDictL)
   outputDictL[0] =  addQTime2dict(copy.deepcopy(outputDictL[0]), fqdn, dates)
   print "- After updating Dict[0]\n%s outputDictL : %s"%(L1, outputDictL)
   if D not in outputDictL[4] :
      outputDictL[4][D] = {}
   print "- Before updating Dict[4]\n%s outputDictL : %s"%(L1, outputDictL)
   outputDictL[4][D] = addQTime2dict(copy.deepcopy(outputDictL[4][D]), fqdn, dates)
   print "- After updating Dict[4]\n%s outputDictL : %s"%(L1, outputDictL)

outputDictL = map( lambda x : {} , range(5))

refList = [("S1", "D1", "f1", "data1"), ("S2", "D1", "f1", "data2")]

for l in refList :
   print "-------------------"
   updateDicts(outputDictL, l[0], l[1], l[2], [l[3]])
   print "-------------------\n"

Program2输出:

-------------------
--- fqdn : f1, dates : ['data1']
- Before updating Dict[0]
    outputDictL : [{}, {}, {}, {}, {}]
    adding key : f1 dates : ['data1']
- After updating Dict[0]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {}]
- Before updating Dict[4]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {}}]
    adding key : f1 dates : ['data1']
- After updating Dict[4]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
-------------------

-------------------
--- fqdn : f1, dates : ['data2']
- Before updating Dict[0]
    outputDictL : [{'f1': ['data1']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
    adding key : f1 dates : ['data2']
- After updating Dict[0]
    outputDictL : [{'f1': ['data1', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
- Before updating Dict[4]
    outputDictL : [{'f1': ['data1', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1']}}]
    adding key : f1 dates : ['data2']
- After updating Dict[4]
    outputDictL : [{'f1': ['data1', 'data2']}, {}, {}, {}, {'D1': {'f1': ['data1', 'data2']}}]
-------------------

f1:data2只在每个字典中插入一次。这就是我们想要的。

3 个答案:

答案 0 :(得分:1)

两个词典中的值都是相同的,因为python只存储对象的引用。将列表分配给两个不同词典中的值时,实际存储在这些词典中的是对同一列表的引用。因此,您实际上只创建了一个列表,只使用两个词典中的引用来修改单个列表。您可以在以下简单示例中看到此行为:

>>> l1 = []
>>> l2 = l1
>>> l2.append('item')
>>> l1
['item']
>>> l2
['item']

变量l1和l2都指向相同的实际列表。使用deepcopy产生期望结果的原因是它创建了一个全新的列表,其中填充了与原始列表相同的值。

关于addQTime2dict功能的一个额外注意事项:因为您在致电key时已确认dictionary不在update,因此效果相同使用更简单的dictionary[key] = dates

答案 1 :(得分:1)

您正在共享两个dicts之间的日期列表的引用。将列表添加到字典时,您应该制作副本以防止此共享

def addQTime2dict(dictionary, key, dates):
   #"%s       k %s, v: %s"%(L6, key, value)
   print "%s adding key : %s dates : %s"%(L1, key, dates)
   if key in dictionary:
      dictionary[key].extend(dates)
   else:
      dictionary[key] = dates[:] # copy of dates

答案 2 :(得分:0)

这是相当多的代码,但我认为dict.has_key()方法可以解决您的问题。例如,在您的第一个列表中:

def addQTime2dict(dictionary, key, dates):
   #"%s       k %s, v: %s"%(L6, key, value)
   print "%s adding key : %s dates : %s"%(L1, key, dates)
   if dictionary.has_key(key):
      dictionary[key].extend(dates)
   else :
      dictionary.update({key : dates})