1

我正在对实例变量进行一些计算,完成后我想腌制类实例,这样我就不必再次进行计算了。这里有一个例子:

import cPickle as pickle

class Test(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = None
    def compute(self, x):
        print 'calculating c...'
        self.c = x * 2

test = Test(10, 'hello')
test.compute(6)

# I have computed c and I want to store it, so I don't have to recompute it again:

pickle.dump(test, open('test_file.pkl', 'wb'))

test.compute(6)我可以检查以查看是什么之后test.__dict__

>>> test.__dict__
{'a': 10, 'c': 12, 'b': 'hello'}

我认为这就是要腌制的东西;然而,

当我去加载类实例时:

import cPickle as pickle

from pickle_class_object import Test

t2 = pickle.load(open('test_file.pkl', 'rb'))

我在外壳中看到了这个:

calculating c...

这意味着我没有腌制c,我正在重新计算它。

有没有办法腌制test我想要的方式?所以我不必重新计算c。我看到我可以 pickle test.__dict__,但我想知道是否有更好的解决方案。此外,我对这里发生的事情的理解很弱,所以任何关于发生的事情的评论都会很棒。我已经阅读了__getstate__and __setstate__,但我不知道如何在这里应用它们。

4

3 回答 3

3

pickle_class_object再次导入模块,Python 运行该模块中的所有代码。

您的顶级模块代码包括对 的调用.compute(),这就是被调用的内容。

您可能希望将创建泡菜的代码移出模块,或将其移至受if __name__ == '__main__':保护的部分:

if __name__ == '__main__':
    test = Test(10, 'hello')
    test.compute(6)

    pickle.dump(test, open('test_file.pkl', 'wb'))

仅当将 python 文件作为主脚本运行时才__name__设置为__main__; 当作为模块导入时,__name__设置为模块名称,if分支将不会运行。

于 2013-05-19T19:32:29.870 回答
2

酸洗按您期望的那样工作。这里的问题是当你运行新脚本时,你导入了包含 class 的模块Test。整个模块都在运行,包括您创建的位test

处理此类事情的典型方法是保护if __name__ == "__main__:块中的内容。

class Test(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = None
    def compute(self, x):
        print 'calculating c...'
        self.c = x * 2

if __name__ == "__main__":
    import cPickle as pickle

    test = Test(10, 'hello')
    test.compute(6)

    # I have computed c and I want to store it, so I don't have to recompute it again:

    pickle.dump(test, open('test_file.pkl', 'wb'))
于 2013-05-19T19:32:18.280 回答
1

这不是正在发生的事情。您导入一个在顶层包含代码的 python 模块,该模块在您导入模块时执行。您可以看到您的代码按预期工作:

import cPickle as pickle

class Test(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = None
    def compute(self, x):
        print 'calculating c...'
        self.c = x * 2

test = Test(10, 'hello')
test.compute(6)

pickle.dump(test, open('test_file.pkl', 'wb'))

t2 = pickle.load(open('test_file.pkl', 'rb'))
print t2.c


--output:--
calculating c...
12

如果您的代码如您所描述的那样工作,那么您会看到“计算 c...”两次。

于 2013-05-19T19:39:27.660 回答