C++ C++;取代Python pickle的数据存储
今年秋天,我用Python为一个编程类做了一个项目,其中有一个20个问题风格的游戏,将从用户的回答中学习。它使用一个基于对问题的“是/否”回答的树,并将每个决策的唯一问题与到达“分支”末端的动物一起腌制C++ C++;取代Python pickle的数据存储,c++,python,pickle,C++,Python,Pickle,今年秋天,我用Python为一个编程类做了一个项目,其中有一个20个问题风格的游戏,将从用户的回答中学习。它使用一个基于对问题的“是/否”回答的树,并将每个决策的唯一问题与到达“分支”末端的动物一起腌制 到课结束时,我们在C++中做了一些工作(但是我在这方面还是很新的),我希望在我的休息时间里做一个C++版本的项目,这将使它更容易运行,例如,一个可执行文件。但是,我发现C++对于泡菜风格的数据存储没有很多选择,我认为Soop.Services序列化或Booj.Python对于这种情况来说将是特别
到课结束时,我们在C++中做了一些工作(但是我在这方面还是很新的),我希望在我的休息时间里做一个C++版本的项目,这将使它更容易运行,例如,一个可执行文件。但是,我发现C++对于泡菜风格的数据存储没有很多选择,我认为Soop.Services序列化或Booj.Python对于这种情况来说将是特别好的。p> <是否有其他的选择,或者你有什么建议如何用C++的另一种方式处理数据?
原始Python代码包括以下内容: def check(self):
correct, lastnode = self.ask(self.root) #lastnode is the closest guess to the new animal
if correct =='n':
print("Rats! I didn't get it. Please help me improve.")
newanimal = AnTreeNode(input("What is your animal? "))
oldanimal = lastnode
newquestion = input("Please enter a yes/no question that would\n select between a(n) %s \
and a(n) %s: " %(newanimal,lastnode.data))+" "
direction = input("What would be the correct answer for a(n) %s? " %newanimal)
newnode = AnTreeNode(newquestion, parent = lastnode.parent)
if lastnode.parent == None:
self.root = newnode
elif lastnode.parent.yes == lastnode:
newnode.parent.yes = newnode
else:
newnode.parent.no = newnode
if direction == 'y':
newnode.yes, newnode.no = newanimal, oldanimal
elif direction == 'n':
newnode.yes, newnode.no = oldanimal, newanimal
newanimal.parent = newnode
oldanimal.parent = newnode
self.dumpTree()
elif correct == 'y':
print("I am soooo smart!")
def loadTree(self):
try:
f = open(self.treefile, "rb")
self.root = pickle.load(f)
except:
self.root = AnTreeNode("frog")
def dumpTree(self):
pickle.dump(self.root, open(self.treefile, 'wb'))
如果我将数据保存到一个文件或数组中,我想不出一种方法来让树工作(我并不特别想创建一个动态数组,尽管我可以确定在一个数组中存储的东西是否可以工作。)问题是,我不确定如何引用特定节点。还有其他选择吗,或者关于如何处理这些问题的想法?谢谢(圣诞快乐!)实际上boost::序列化工作得很好,学习基础知识并不那么困难
但是,您可能会考虑一些更高级的类库协议缓冲区。这样你就可以拥有既可以用于Python又可以用于C++版本的数据库。 EDIT:boost::python不是正确的解决方案,因为它只允许进行绑定。使用它来保存数据将是一件非常痛苦的事情
BooServices允许序列化(然后很容易地保存在磁盘上)C++结构。请尝试文档中的示例
协议缓冲区是一种序列化格式,允许以二进制格式交换数据。格式定义良好,因此您可以从不同的语言进行读/写并交换数据。 在代码内部更容易操作,例如XML实例:但是,我认为它需要比boost::serialize多一点努力。任何方法都值得学习,并且对进一步的项目也有用。 < P>有一个开源C++库 这允许您在C++中处理对象(可能允许您重用)。 Python项目中的pickle文件)。它最适合序列化标准 Python数据结构(dict、list、tuple、int、float等),但可以工作 对于有一些工作的类(毕竟,Python类通常使用 名称空间的dict) 演示如何使用picklingtools库(并使其工作)的简单示例 用C++和Python)< /P>
这样,你可以在C++和Python之间来回翻阅字典或者做列表,然后做你需要的。你可以按原样使用一切
关于如何在C++中进行酸洗和解菜的研究有重要的文献资料。 “文档”选项卡下的网站。最好的开始地点可能是 用这个 警告!前面有危险! 您可以用C++来序列化类(这样,Python中的同一类将具有C++等价),但它是重要的;y更难:如果你能呆在家里 标准的Python数据结构,您的生活会轻松得多。要做到这一点,你必须 然后用它的构造函数登记C++类 用这个系统。您必须具有构建函数(请参见下面的简单示例): 你可以让它工作,这样你就可以拥有Python和C++类了。 同样的感觉,用pickle来交流,但这比看起来要难 (部分原因是因为C++没有实际的运行时自省概念(它只限于 RTTI),所以你倾向于用元组来描述整个C++类。 字典,手动列表。然后向pickle加载程序注册这些函数。 这是可以做到的,但考虑到你问题的简单性质,我会坚持 常用Python数据结构(列表、dict、元组、int、float、字符串、None)并用它们来表示您的20个问题树。添加一些代码是一件好事。然而,试着专注于一些特定的狙击集。我们不需要猜测部分,因为您只对保存到磁盘感兴趣。所以大多数人都很懒惰,我们不会努力找到具体的部分好的,谢谢,我改变了。什么是协议缓冲区?那么,Python是否会无关紧要,只要我在C++中运行它?(很抱歉,我在这方面很新,但是你说学习基础知识并不那么困难——我发现的大部分信息都是在Python和C++之间切换的。如果我不在Python中读取泡菜数据库,我还有什么要记的吗?)
#include "chooseser.h"
#include <iostream>
int main (int argc, char **argv)
{
// Create a Python style dictionary
Val v = Tab("{'a':1, 'b':2.2, 'c':'three', 'nested':{ 'zz':1 }");
v["d"] = "something";
// print out a nested key
cout << v["nested"]["zz"] << endl;
// Pickle the data structure to disk
DumpValToFile(v, "state.p0", SERIALIZE_P2);
// # Python side would read this same file with
// >>> import cPickle
// >>> result = cPickle.load( file('state.p0') ) # load fiigures out which prototcol
}
questions_dict = { 'data': 'COW', 'left': None, 'right': { ''data':'CAT', left': None, 'right': None } }
print questions_dict['right']['data'] # Right child's data
LEFT = 1; RIGHT = 2; DATA = 0
questions_list = ["COW", None, ["CAT", None, None] ]
print questions_list[RIGHT][DATA] # Right child's data
// When registering things with the factory, they take in some tuple
// and return a Val: REDUCE tend to be more for built-in complicated
// types like Numeric, array and complex. BUILD tends to more for
// user-defined types.
typedef void (*FactoryFunction)(const Val& name,
const Val& input_tuple,
Val& environment,
Val& output_result);
// Example of how user-defined classes would probably serialize: the
// user-defined classes tend to be built with BUILD instead of REDUCE,
// which passes slightly different arguments to the tuple. As an
// example, magine a simple Python class:
//
// class Scott(object) :
// def __init__(self, n) : self.data = int(n)
//
// A dumps(a,2) (where a= Scott(100)) looks like
// '\x80\x02c__main__\nScott\nq\x01)\x81q\x02}q\x03U\x04dataq\x04Kdsb.'/
//
// type_object: a tuple (string_name, args). i.e., ('__main__\nScott\n', ())
// input: a dictionary i.e., {'data', 100 }
inline void BuildScottFactoryFunction (const Val& type_object,
const Val& input,
Val& /* environment */,
Val& output_result)
{
cout << "SCOTT:type_object:" << type_object << endl;
cout << "SCOTT:input:" << input << endl;
string name = type_object(0);
Tup& args = type_object(1);
cout << "name:" << name << " args:" << args << endl;
if (name!="__main__\nScott\n") throw runtime_error("Not right name");
Val& result = input("data");
output_result = result;
}
PickleLoader p(buffer, buffer_len);
p.registerFactory("__main__\nScott\n", BuildScottFactoryFunction);