我正在对一个实例变量进行一些计算,在完成之后我想要腌制类实例,这样我就不必再进行计算了。这是一个例子:
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'))
我在shell中看到了这一点:
calculating c...
这意味着我没有挑剔c
而我正在重新计算它。
有没有办法腌制test
我想要的方式?所以我不必重新计算c
。我看到我可以挑剔test.__dict__
,但我想知道是否有更好的解决方案。此外,我对这里发生的事情的理解很薄弱,所以对任何事情的评论都会很棒。我读过__getstate__
和__setstate__
,但我不知道如何在这里应用它们。
答案 0 :(得分:3)
您正在再次导入pickle_class_object
模块,Python在该模块中运行所有代码。
您的顶级模块代码包含对.compute()
的调用,这就是所调用的内容。
您可能想要移动创建该模块的pickle out 的代码,或将其移至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
分支将不会运行。
答案 1 :(得分:2)
酸洗工作正如您所期望的那样起作用。这里的问题是当您运行新脚本时,您导入包含类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'))
答案 2 :(得分: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 ...”两次。