【问题标题】:append in a list causing value overwrite附加在列表中导致值覆盖
【发布时间】:2012-08-22 03:39:14
【问题描述】:

我面临一个特殊的问题。我将在下面简要描述 假设我有这段代码-

class MyClass:

   __postBodies = []
    .
    .
    .
for the_file in os.listdir("/dir/path/to/file"):
      file_path = os.path.join(folder, the_file)
      params = self.__parseFileAsText(str(file_path)) #reads the file and gets some parsed data back
      dictData = {'file':str(file_path), 'body':params}
      self.__postBodies.append(dictData)
      print self.__postBodies
      dictData = None
      params = None

问题是,当我每次为不同的文件打印 params 和 dictData 时,它都有不同的值(正确的事情),但是一旦发生追加,我打印 __postBodies 就会发生奇怪的事情。如果有你的文件,假设A,B,C,那么

第一次 __postBodies 有内容 = [{'body':{A dict with some 与文件 A} 相关的数据,'file':'path/of/A'}]

第二次变成 = [{'body':{一个包含一些数据的字典 file B}, 'file':'path/of/A'}, {'body':{A dict with some data related to 文件 B}, 'file':'path/of/B'}]

AND 第三次 = [{'body':{A dict with some data relaed to file C}, 'file':'path/of/A'}, {'body':{A dict with some data related to file C}, 'file':'path/of/B'}, {'body':{A dict with some data related to file C}, '文件':'路径/的/C'}]

所以,您会看到“文件”键工作正常。奇怪的是,所有条目的“body”键都被覆盖,最后附加了一个。

我犯了什么错误吗?我有什么需要做的吗?请指点我一个方向。

对不起,如果我不是很清楚。

编辑------------

self.__parseFileAsText(str(file_path)) 调用的返回是一个字典,我将其作为“正文”插入到 dictData 中。

EDIT2 ----------------------------

如你所问,这是代码,但我检查了 params = self.__parseFileAsText(str(file_path)) 调用每次都返回一个 diff dict。

def __parseFileAsText(self, fileName):

        i = 0
        tempParam = StaticConfig.PASTE_PARAMS

        tempParam[StaticConfig.KEY_PASTE_PARAM_NAME] = ""
        tempParam[StaticConfig.KEY_PASTE_PARAM_PASTEFORMAT] = "text"
        tempParam[StaticConfig.KEY_PASTE_PARAM_EXPIREDATE] = "N"
        tempParam[StaticConfig.KEY_PASTE_PARAM_PRIVATE] = ""
        tempParam[StaticConfig.KEY_PASTE_PARAM_USER] = ""
        tempParam[StaticConfig.KEY_PASTE_PARAM_DEVKEY] = ""
        tempParam[StaticConfig.KEY_PASTE_FORMAT_PASTECODE] = ""

        for line in fileinput.input([fileName]):
            temp = str(line)
            temp2 = temp.strip()
            if i == 0:              
                postValues = temp2.split("|||")

                if int(postValues[(len(postValues) - 1)]) == 0 or int(postValues[(len(postValues) - 1)]) == 2:
                    tempParam[StaticConfig.KEY_PASTE_PARAM_NAME] = str(postValues[0])

                    if str(postValues[1]) == '':                                        
                        tempParam[StaticConfig.KEY_PASTE_PARAM_PASTEFORMAT] = 'text'
                    else:
                        tempParam[StaticConfig.KEY_PASTE_PARAM_PASTEFORMAT] = postValues[1]

                    if str(postValues[2]) != "N":
                        tempParam[StaticConfig.KEY_PASTE_PARAM_EXPIREDATE] = str(postValues[2])

                    tempParam[StaticConfig.KEY_PASTE_PARAM_PRIVATE] = str(postValues[3])
                    tempParam[StaticConfig.KEY_PASTE_PARAM_USER] = StaticConfig.API_USER_KEY
                    tempParam[StaticConfig.KEY_PASTE_PARAM_DEVKEY] = StaticConfig.API_KEY

                else:
                    tempParam[StaticConfig.KEY_PASTE_PARAM_USER] = StaticConfig.API_USER_KEY
                    tempParam[StaticConfig.KEY_PASTE_PARAM_DEVKEY] = StaticConfig.API_KEY
                i = i+1
            else:
                if tempParam[StaticConfig.KEY_PASTE_FORMAT_PASTECODE] != "" :           
                    tempParam[StaticConfig.KEY_PASTE_FORMAT_PASTECODE] = str(tempParam[StaticConfig.KEY_PASTE_FORMAT_PASTECODE])+"\n"+temp2
                else:
                    tempParam[StaticConfig.KEY_PASTE_FORMAT_PASTECODE] = temp2

        return tempParam

【问题讨论】:

  • 你能显示self.__parseFileAsText的代码吗?看起来同一个字典正在被重复使用,这导致 'body' 键的值每次都被更改。
  • 帮自己一个忙,不要使用双下划线名称。一个下划线就足以表明其他人不应该使用它。
  • 谢谢内德。会记住的:)

标签: python


【解决方案1】:

每次调用MyClass.__parseFileAsText() 时,您都可能返回同一个字典,这可能是发生这种情况的几种常见方式:

  • __parseFileAsText() 接受 mutable default argument(您最终返回的字典)
  • 您修改类或实例的属性并将其返回,而不是每次都创建一个新属性

确保在每次调用 __parseFileAsText() 时都创建一个新字典应该可以解决此问题。

编辑:根据您对__parseFileAsText() 代码的更新问题,您的问题是您在每次调用时都重复使用同一个字典:

tempParam = StaticConfig.PASTE_PARAMS
...
return tempParam

在每次调用时,您都在修改StaticConfig.PASTE_PARAMS,最终结果是您列表中的所有正文字典实际上都是对StaticConfig.PASTE_PARAMS 的引用。根据 StaticConfig.PASTE_PARAMS 是什么,您应该将顶行更改为以下内容之一:

# StaticConfig.PASTE_PARAMS is an empty dict
tempParam = {}

# All values in StaticConfig.PASTE_PARAMS are immutable
tempParam = dict(StaticConfig.PASTE_PARAMS)

如果StaticConfig.PASTE_PARAMS 中的任何值是可变的,您可以使用copy.deepcopy,但最好使用您自己的这些默认值填充tempParam

【讨论】:

  • 你是对的。我真傻。无论如何,现在已经完成了。感谢您的帮助:)
【解决方案2】:

如果__postBodies 不是现在定义的类属性,而只是实例属性怎么办?

【讨论】:

  • 我认为在我的情况下,作为一个类属性很好,因为我在其他地方只使用一个对 MyClass 的引用来调用完成这项工作的函数。但是对于不是这种情况的情况,您是正确的。可以在这里找到一个很好的参考 - stackoverflow.com/questions/207000/…
猜你喜欢
  • 1970-01-01
  • 2016-03-12
  • 2021-04-06
  • 2023-04-04
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 2020-04-25
相关资源
最近更新 更多