简体   繁体   English

为什么pickle.dumps会调用__getattr__?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM