2012-08-23 41 views
3
import cPickle 

class Foo(object): 
    def __init__(self): 
     self._data = {'bar': 'baz'} 

    def __getattr__(self, name): 
     assert hasattr(self, '_data') 
     return self._data[name] 

    # I even had to define this just to stop KeyError: '__getstate__' 
    def __getstate__(self): 
     return self.__dict__ 

foo = Foo() 
bar = cPickle.dumps(foo) 
cPickle.loads(bar) 

这会引发断言错误。为什么pickle.dumps调用__getattr__?

我想pickle/cPickle刚刚转成__dict__倾倒当一个字符串,然后使用该字符串直接加载时设置的新对象的__dict__。为什么dumps需要拨打bar.__getattr__?如何更改Foo以避免这种情况?

+0

移动回答。 –

回答

2

根据对cPickle的文档:http://docs.python.org/library/pickle.html

object.__getstate__() 

类可以进一步影响它们的实例是如何腌制;如果类定义了方法__getstate__(),它将被调用,并且将返回状态作为实例的内容进行挑选,而不是实例字典的内容。如果没有__getstate__()方法,则会腌制实例的__dict__

在在unpickle时,一些方法,如__getattr__()__getattribute__(),或者__setattr__()可在实例调用。如果这些方法依赖于某种内部不变量,则 类型应实现__getinitargs__()__getnewargs__()至 建立这样一个不变量;否则,__new__()__init__()都不会被调用。

既然你正试图断言hasattr(self, '_data')是真的,我相信你需要使用__getinitargs__()__getnewargs__()。这是因为使用泡菜时,不会调用类__init__方法。

相关问题