【问题标题】:How to save a list of ojects that contains a list as member to file by using pickle python?如何使用pickle python将包含列表的对象列表保存为文件成员?
【发布时间】:2015-03-06 08:38:14
【问题描述】:

我有以下课程:

class Document:
  _queryID  = ""
  _name = []
  _docId = ""

在代码中,我创建了一个名为 listDocuments 的列表。我用 Document 类型的对象填充列表。

import pickle 
if __name__ == "__main__": 
   listDocuments = []
   for i in range(0,10):
      e = Document()
      e._queryID = str(i)
      e._docId   = str(i+1)
      e._name.append("h"+str(i))
      listDocuments.append(e)
   save_data(listDocuments, "Variations.dat")
   list = load_data("Variations.dat")

   for obj  in listEntities:
     print obj._queryID  + "==>"+ obj._docId
     for var in obj._name:
       print var +"  "
     print "----\n"

我使用了以下来自Python: how to save a list with objects in a file的函数:

#save list of variations
def save_data(data, path):
    with open(path, "wb") as f:
        pickle.dump(data, f)

#load list of variations (Correctd after comments thank you)
def load_data(var_file):
    try:
        with open(var_file) as f:
            listDocument = pickle.load(f)
    except:
        listDocument = []

    return listDocument

  • 作为输出,我只能打印 _queryID。我错过了什么?我不能 打印列表 _name 和 _docID

【问题讨论】:

  • 我无法重现问题,它似乎对我来说工作正常。您能否发布用于打印列表_name 的代码?另外,我会避免命名变量 list(在您的第二个代码块中),并且您在 try 中缺少 listDocuments

标签: python pickle


【解决方案1】:

好的,有几个问题。

第一:

def load_data(var_file):
    try:
        with open(var_file) as f:
            listDocument = pickle.load(f)
    except:
        listDocuments = []

    return listDocuments

您同时使用listDocumentlistDocuments。 (注意一个有一个尾随s)。此外,您在隐藏错误的外部程序中使用了这些变量listDocuments。让我们将函数内部的变量重命名为 data,就像 save_data 函数一样。出于相同的一致性原因,我们还将 var_file 重命名为 path

考虑:

def load_data(path):
    data = []
    try:
        with open(path) as f:
            data = pickle.load(f)
    except: pass

    return data

接下来,您将使用 list,它是一个保留的内置 - 让我们将其更改为 lst。所以现在你有:

class Document:
    _queryID  = ""
    _name = []
    _docId = ""

def save_data(data, path):
    with open(path, "wb") as f:
        pickle.dump(data, f)

#load list of variations
def load_data(path):
    data = []
    try:
        with open(path) as f:
            data = pickle.load(f)
    except: pass

    return data

import pickle
if __name__ == "__main__":
    listDocuments = []
    for i in range(0,10):
        e = Document()
        e._queryID = str(i)
        e._docId   = str(i+1)
        e._name.append("h"+str(i))
        listDocuments.append(e)
    save_data(listDocuments, "Variations.dat")
    lst = load_data("Variations.dat")

    for elem in lst:
        print elem._queryID
        print elem._docId
        print elem._name
        print "---"

哪个有效,并打印:

0
1
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
1
2
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
2
3
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
3
4
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
4
5
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
5
6
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
6
7
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
7
8
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
8
9
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---
9
10
['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9']
---

编辑

根据您的编辑,您没有 listEntities 变量——我认为您的意思是(最近重命名的)lst

for obj in lst:
    print obj._queryID  + "==>"+ obj._docId
    for var in obj._name:
        print var +"  "
    print "----\n"

最后,如果您想知道为什么 _name 变量对于 Document 类的所有实例都是相同的,那是因为您将 _name 声明为类属性(所以它对于所有实例都是相同的),而不是实例属性。

您可以将 Document 类定义替换为:

class Document:
    def __init__(self):
        self._name = []

您可能会对结果更满意:

0==>1
h0  
----

1==>2
h1  
----

2==>3
h2  
----

3==>4
h3  
----

4==>5
h4  
----

5==>6
h5  
----

6==>7
h6  
----

7==>8
h7  
----

8==>9
h8  
----

9==>10
h9  
----

【讨论】:

  • 我想知道我错过了什么。我不知道我应该将它声明为类属性。我实际上将类视为一种结构,就像在 C++ 中一样。希望我在这方面也没有错。好吧,我认为这个答案是 double 更正 lololol
  • 不用担心,您编写Document 定义的方式类似于C++ 中的static 概念。这些属性将由类的每个实例共享。如果你想要独立的实例属性,你可以把它们放在__init__ 方法中,在它们前面加上self.(就像我写的self._name)。请注意,在 Python 中,与 C++ 不同,您不需要 这样做。在_name 的情况下,您需要初始化它,因为您稍后将在append 中使用它,但在_queryID_docId 的情况下您不需要,这就是我省略初始化的原因。 (存在例外/怪异)
猜你喜欢
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2019-12-29
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多