【问题标题】:Why does pickle.dumps call __getattr__?为什么 pickle.dumps 调用 __getattr__?
【发布时间】:2012-08-23 23:55:05
【问题描述】:
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 以避免这种情况?

【问题讨论】:

    标签: python serialization pickle


    【解决方案1】:

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

    object.__getstate__()
    

    类可以进一步影响其实例的腌制方式;如果该类定义了方法__getstate__(),则调用该方法并将返回状态腌制为实例的内容,而不是实例字典的内容。如果没有__getstate__() 方法,则实例的__dict__ 被腌制。

    注意

    在 unpickling 时,一些方法如__getattr__(), 可以在实例上调用__getattribute__()__setattr__()。如果这些方法依赖于某些内部不变量为真,则 类型应该实现 __getinitargs__()__getnewargs__() 到 建立这样的不变量;否则,__new__()__init__() 将被调用。

    由于您试图断言hasattr(self, '_data') 为真,我相信您需要使用__getinitargs__()__getnewargs__()。这是因为在使用 pickle 时,不会调用 classes__init__ 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-22
      • 2012-09-19
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      相关资源
      最近更新 更多