[英]Why does pickle.dumps call __getattr__?
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)
This raises an assertion error. 这会引发断言错误。
I thought pickle
/ cPickle
just turns __dict__
into a string when dumping and then uses that string to set the __dict__
of the new object directly when loading. 我以为pickle
/ cPickle
在转储时只是将__dict__
转换为字符串,然后在加载时使用该字符串直接设置新对象的__dict__
。 Why would dumps
need to call bar.__getattr__
? 为什么dumps
需要调用bar.__getattr__
? How can I change Foo
to avoid that? 如何更改Foo
以避免这种情况?
According the documentation for cPickle: http://docs.python.org/library/pickle.html 根据cPickle的文档: http : //docs.python.org/library/pickle.html
object.__getstate__()
Classes can further influence how their instances are pickled; 类可以进一步影响其实例的腌制方式。 if the class defines the method
__getstate__()
, it is called and the return state is pickled as the contents for the instance, instead of the contents of the instance's dictionary. 如果该类定义了方法__getstate__()
,则会调用该方法,并将返回状态作为实例的内容(而不是实例的字典的内容)进行腌制。 If there is no__getstate__()
method, the instance's__dict__
is pickled. 如果没有__getstate__()
方法,则对实例的__dict__
进行腌制。Note 注意
At unpickling time, some methods like
__getattr__()
,__getattribute__()
, or__setattr__()
may be called upon the instance. 在解开时间,可能会在实例上调用__getattr__()
,__getattribute__()
__setattr__()
或__setattr__()
之类的方法。 In case those methods rely on some internal invariant being true, the type should implement either__getinitargs__()
or__getnewargs__()
to establish such an invariant; 如果这些方法依赖于某个内部不变式为真,则该类型应实现__getinitargs__()
或__getnewargs__()
来建立这样的不变式; otherwise, neither__new__()
nor__init__()
will be called. 否则,将不会__new__()
和__init__()
。
Since you are trying to assert that hasattr(self, '_data')
is True, I believe that you need to use __getinitargs__()
or __getnewargs__()
. 由于您试图断言hasattr(self, '_data')
__getinitargs__()
hasattr(self, '_data')
为True,因此我相信您需要使用__getinitargs__()
或__getnewargs__()
。 This is because when using pickle, a classes __init__
method is not called. 这是因为使用泡菜时,不会调用__init__
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.