python - 为什么我未 pickle 的顺序与 pickle 时的顺序不同?

标签 python python-2.7 pickle

我对 python 变量持久性有点困惑,在我的代码中,我使用以下代码使模型参数在某些迭代期间持久化

 with open('W_Hs_Hu_iter'+str(inx)+'.pickle', 'wb') as f:
        pickle.dump((self.W,self.Hs,self.Hu),f)

在长时间的迭代之后,我尝试用

加载模型
with open('W_Hs_Hu_iter450.pickle', 'rb') as f:
    W,Hs,Hu= pickle.load(f)
    #W,Hu,Hs= pickle.load(f)

但是我查了一下,Hs和Hu的顺序错了?那会发生吗?

最佳答案

这是一个类实例的 pickle,其中属性值在 pickle 之后交换。

>>> class Foo(object):
...   a = 1
...   b = 2
...   def __init__(self, c,d):
...     self.c = c
...     self.d = d
...   def bar(self):
...     return self.a,self.b,self.c,self.d
... 
>>> f = Foo(3,4)
>>> _f = pickle.dumps(f)
>>> f.c,f.d = f.d,f.c
>>> f.b,f.a = f.a,f.b
>>> f_ = pickle.loads(_f)
>>> f_.bar()
(1, 2, 3, 4)
>>> f.bar()
(2, 1, 4, 3)

所以,这按预期工作。但是,python 通过引用对类进行 pickle,因此如果您更改类定义,它似乎会更改实例属性。

>>> g = Foo(3,4)
>>> _g = pickle.dumps(g)
>>> g.c,g.d = g.d,g.c
>>> Foo.a,Foo.b = Foo.b,Foo.a
>>> g_ = pickle.loads(_g)
>>> g_.bar()
(2, 1, 3, 4)
>>> g.bar()
(2, 1, 4, 3)

如果您将列表或其他一些序列作为类属性,这一点会更加明显。因此,让我们向类中添加一些列表对象。

>>> Foo.a = []
>>> Foo.zap = lambda self:self.a
>>> Foo.baz = lambda self,x:self.a.append(x)
>>> 
>>> h = Foo(3,4)
>>> h.baz(0)
>>> h.baz(1)
>>> h.zap()
[0, 1]
>>> _h = pickle.dumps(h)
>>> h.baz(2)
>>> h.baz(3)
>>> h_ = pickle.loads(_h)
>>> h_.zap()
[0, 1, 2, 3]

这是因为列表的值实际上存储在类属性而不是实例属性上。这是此类行为的众多示例之一。

如果您想“按原样”保留实例(即不通过引用存储),那么您应该使用 dill 进行 pickle 。但是,莳萝 的 pickle 会更大。

>>> import dill
>>> _h = dill.dumps(h)
>>> h.baz(4)
>>> h.baz(5)
>>> h_ = dill.loads(_h)
>>> h_.zap()
[0, 1, 2, 3]
>>> h.zap()
[0, 1, 2, 3, 4, 5]

关于python - 为什么我未 pickle 的顺序与 pickle 时的顺序不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32933522/

相关文章:

python - QPixmap(图像)的图 block 具有重叠区域

python - 匹配来自 python re 的单引号

python - 检查 None、False、True

python - 无法使用 pickle Python 写入二进制文件

python - 如何将小时添加到时间戳

Python tarfile 不解压

python - "Expected type ' Union[str, bytearray] ' got ' int ' instead"write 方法警告

Python- dill : Can't pickle decorated class

Python pickle : fix\r characters before loading

Python 套接字实现