2013-04-12 90 views
0

我試圖儘可能簡化這個操作。基本上我想把數據保存到一個文件中,然後檢索它,以便questor.py能夠工作,並且可以「記住」它在機器上教過的所有內容。原始代碼可在網上找到http://www.strout.net/info/coding/python/questor.py 如果我正在閱讀代碼,最終會看到類似{key:{key:{key:class instance},class instance},class instance}的對象。 (粗略估計)在Python 2.7中使用嵌套類實例保存字典

請忽略未完成的方法保存,我一直在研究如何在不丟失任何嵌入實例的情況下醃製字典。

以下是我試圖通過pickler保存字典的嘗試。有些代碼是未完成的,但你應該能夠知道我想要做什麼。到目前爲止,我所能做的就是檢索最後一個問題/答案集。我的泡菜不是保存嵌入的實例,或者當我保存泡菜時,他們實際上並不存在。我儘可能地遵循意大利麪條線,但似乎無法弄清楚如何設置保存文件的方式而不會丟失任何東西。 另外我的文件不一定是.txt,我原先打算使用.data作爲pickle。浮現在腦海

# questor.py 

# define some constants for future use 
kQuestion = 'question' 
kGuess = 'guess' 
questfile = 'questfile.txt' 

## Added 
import cPickle as p 
# create a file for questor 
def questor_file(): 
    try: 
     questor = open(questfile,'rb') 
     try: 
      q = p.Unpickler(questor) 
      quest = q.load() 
      questor.close() 
      return quest 
     except: 
      print 'P.load failed' 
    except: 
     print 'File did not open' 
     questor = open('questfile.data', 'wb') 
     questor.close() 
    return Qnode('python') 

# define a function for asking yes/no questions 
def yesno(prompt): 
    ans = raw_input(prompt) 
    return (ans[0]=='y' or ans[0]=='Y') 

# define a node in the question tree (either question or guess) 
class Qnode: 

    # initialization method 
    def __init__(self,guess): 
     self.nodetype = kGuess 
     self.desc = guess 

    ##Added 
    ## Not sure where I found this, but was going to attempt to use this as a retreival method 
    ## haven't gotten this to work yet 
    def Load(self): 
     f = open(self.questfile,'rb') 
     tmp_dict = cPickle.load(f) 
     f.close()  
     self.__dict__.update(tmp_dict) 

    ##Added 
    # was going to use this as a save method, and call it each time I added a new question/answer 
    def Save(self,node): 
     f = open(self.questfile,'wb') 
     quest = p.pickler(f) 


    # get the question to ask 
    def query(self): 
     if (self.nodetype == kQuestion): 
      return self.desc + " " 
     elif (self.nodetype == kGuess): 
      return "Is it a " + self.desc + "? " 
     else: 
      return "Error: invalid node type!" 

    # return new node, given a boolean response 
    def nextnode(self,answer): 
     return self.nodes[answer] 

    # turn a guess node into a question node and add new item 
    # give a question, the new item, and the answer for that item 
    def makeQuest(self, question, newitem, newanswer): 

     # create new nodes for the new answer and old answer 
     newAnsNode = (Qnode(newitem)) 
     oldAnsNode = (Qnode(self.desc)) 

     # turn this node into a question node 
     self.nodetype = kQuestion 
     self.desc = question 

     # assign the yes and no nodes appropriately 
     self.nodes = {newanswer:newAnsNode, not newanswer:oldAnsNode} 
     self.save(self.nodes) 


def traverse(fromNode): 
    # ask the question 
    yes = yesno(fromNode.query()) 

    # if this is a guess node, then did we get it right? 
    if (fromNode.nodetype == kGuess): 
     if (yes): 
      print "I'm a genius!!!" 
      return 
     # if we didn't get it right, return the node 
     return fromNode 

    # if it's a question node, then ask another question 
    return traverse(fromNode.nextnode(yes)) 

def run(): 
    # start with a single guess node 
    # This was supposed to assign the data from the file 
    topNode = questor_file() 


    done = 0 
    while not done: 
     # ask questions till we get to the end 
     result = traverse(topNode) 


     # if result is a node, we need to add a question 
     if (result): 
      item = raw_input("OK, what were you thinking of? ") 
      print "Enter a question that distinguishes a", 
      print item, "from a", result.desc + ":" 
      q = raw_input() 
      ans = yesno("What is the answer for " + item + "? ") 
      result.makeQuest(q, item, ans) 
      print "Got it." 

     # repeat until done 
     print 
     done = not yesno("Do another? ") 
    # Added 
    # give me the dictionary  
    return result 

# immediate-mode commands, for drag-and-drop or execfile() execution 
if __name__ == '__main__': 
    print "Let's play a game." 
    print 'Think of something, just one thing.' 
    print 'It can be anything, and I will try to guess what it is.' 
    raw_input('Press Enter when ready.') 
    print 
    questdata = run() 
    print 
    # Added 
    # Save the dictionary 
    questor = open(questfile,'wb') 
    q = p.Pickler(questor) 
    q.dump(questdata) 
    questor.close() 
    raw_input("press Return>") 
else: 
    print "Module questor imported." 
    print "To run, type: questor.run()" 
    print "To reload after changes to the source, type: reload(questor)" 

# end of questor.py 
+0

我想你想讓你的QClass pickleable?看到這篇文章http://stackoverflow.com/questions/4109848/design-of-a-python-pickleable-object-that-describes-a-file –

+0

對不起,讓我刪除原來的代碼,它是可用的無論如何,我只是給它作爲參考 – user2243208

+0

@Joran Beasley觸及我所需要的,但我能夠醃字典並保存它,甚至從文件中檢索它,我的問題是我失去了所有的嵌套類實例。個別地,我可以醃製課程,問題是我不知道如果我甚至正確理解代碼開始。我對makeQuest的假設是否正確? – user2243208

回答

0

一種方式是創建的所有節點的列表,並保存該...他們應該保持他們的內部指針自己。

在申報文件的頂部節點列表(和使用泡菜...只是導致林更熟悉)

import pickle 
kQuestion = 'question' 
kGuess = 'guess' 
questfile = 'questfile.txt' 
nodes = [] 
.... 

改變你的load方法類似

def questor_file(): 
    global nodes 
    try: 
     questor = open(questfile,'rb') 
     try: 
      nodes= pickle.load(questor) 
      quest = nodes[0] 
      questor.close() 
      return quest 
     except: 
      print 'P.load failed' 
      nodes = [] 

    except: 
     print 'File did not open' 
     nodes = [] 
    return Qnode('python') 

改變你的類的構造函數,以便它把每個節點到節點

class Qnode: 
    # initialization method 
    def __init__(self,guess): 
     self.nodetype = kGuess 
     self.desc = guess 
     nodes.append(self) 

末哪裏它說#added保存字典,保存您的節點列表

questor = open(questfile,'wb') 
q = pickle.dump(nodes,questor) 

確保您的系統提示時輸入不退出程序...

,你也可以將它保存到數據庫或任何但是,你會仍然必須存儲每個節點,它可能會更復雜...這種方法應該真的很好,我認爲,(雖然可能有一種更自然的方式來保存樹結構)...

+0

啊,謝謝我甚至沒有想到這一點,我不知道一個類__init__可以修改一個全局對象,甜,這有助於很多。現在要弄清楚如何讓程序迭代列表或重建列表中的字典,以便下次運行它時,它會「記住」所有舊的東西。 – user2243208

+0

附加程序不會只在實例初始化時將實例附加到列表中,還是允許它在修改實例數據時更改實例數據?換句話說,因爲在實例初始化後dict被改變了,append會添加新的dict每個實例調用嗎? – user2243208

+0

嘗試它;)...它的一個可變對象,所以列表應該更新 –