Python 如何在没有副作用的情况下进行腌制和解腌?

Python 如何在没有副作用的情况下进行腌制和解腌?,python,pickle,Python,Pickle,为什么pickle重用现有的Python类“C”,而不是从pickle字节重建类?有没有一种方法可以让我在没有副作用的情况下泡菜和解饼 以下是我的repl会话: In [1]: import pickle In [2]: class C: ...: pass ...: In [3]: hasattr(C, 'foo') Out[3]: False In [4]: pickled = pickle.dumps(C) In [5]: C.foo = 'bar' In [

为什么pickle重用现有的Python类“C”,而不是从pickle字节重建类?有没有一种方法可以让我在没有副作用的情况下泡菜和解饼

以下是我的repl会话:

In [1]: import pickle

In [2]: class C:
   ...:     pass
   ...:

In [3]: hasattr(C, 'foo')
Out[3]: False

In [4]: pickled = pickle.dumps(C)

In [5]: C.foo = 'bar'

In [6]: hasattr(C, 'foo')
Out[6]: True

In [7]: C_without_foo = pickle.loads(pickled)

In [8]: hasattr(C_without_foo, 'foo')
Out[8]: True

In [9]: hasattr(C, 'foo')
Out[9]: True

我认为问题在于您正在对类本身进行pickle,而不是对特定对象进行pickle

import pickle
class C:
    pass

myC = C() #pickle myC object, not the C class
print(hasattr(myC, 'foo'))

pickled = pickle.dumps(myC)

myC.foo = 'bar'
print(hasattr(myC, 'foo'))

C_without_foo = pickle.loads(pickled)
print(hasattr(C_without_foo, 'foo'))
print(hasattr(myC, 'foo'))

这是因为它们共享相同的标识,即它们指向相同的内存位置。我们对list也有同样的行为

a = [1, 2, 3]
b = a
print(id(a) == id(b)) # True

b.append(4)
print(a) # [1, 2, 3, 4]

c = a.copy()
a.append(5)
print(c)  # [1, 2, 3, 4]
print(id(c) == id(a)) # False
您的问题:

In [1]: import pickle

In [2]: class C:
   ...:     pass
   ...:

In [3]: hasattr(C,'foo')
Out[3]: False

In [4]: pickled = pickle.dumps(C)

In [5]: id(C)
Out[5]: 2887019170312

In [6]: C.foo = 'bar'

In [7]: id(C)
Out[7]: 2887019170312

In [8]: C_ = pickle.loads(pickled)

In [9]: id(C_)
Out[9]: 2887019170312
解决方案。复制一份

In [3]: C_ = type('C_', C.__bases__, dict(C.__dict__))

In [4]: pickled = pickle.dumps(C_)

In [5]: hasattr(C, 'foo')
Out[5]: False

In [6]:  C.foo = 'bar'

In [7]: C_without_foo = pickle.loads(pickled)

In [8]: hasattr(C_without_foo, 'foo')
Out[8]: False

Pickle是一种依赖于很多东西的格式。实际上,您应该只期望数据在同一台机器(或非常类似的机器)上使用相同的代码正确地解除锁定。谢谢。我确实打算pickle类而不是对象。我想在取消勾选该类后构造该对象。