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
/ cPickle
只是在转储时将__dict__
转换为字符串,然后在加载时直接使用该字符串设置新对象的__dict__
。为什么dumps
需要致电bar.__getattr__
?如何更改Foo
以避免这种情况?
答案 0 :(得分:2)
根据cPickle的文档:http://docs.python.org/library/pickle.html
object.__getstate__()
类可以进一步影响他们的实例被腌制的方式;如果类定义方法
__getstate__()
,则调用它并将返回状态作为实例的内容进行pickle,而不是实例的字典的内容。如果没有__getstate__()
方法,则会对实例的__dict__
进行pickle。请注意
在上映时间,某些方法如
__getattr__()
, 可以在实例上调用__getattribute__()
或__setattr__()
。如果这些方法依赖于某些内部不变量为真,那么 类型应该实现__getinitargs__()
或__getnewargs__()
来实现 建立这样的不变量;否则,__new__()
也不是__init__()
将被调用。
由于您试图声明hasattr(self, '_data')
为True,我相信您需要使用__getinitargs__()
或__getnewargs__()
。这是因为在使用pickle时,不会调用类__init__
方法。