为什么pickle会重用现有的Python类'C'而不是从pickled字节中重建该类?有没有办法可以让我腌制和腌制而没有副作用?
这是我的代表会话:
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
答案 0 :(得分:1)
我认为问题在于您正在腌制类本身,而不是特定的对象。
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'))
答案 1 :(得分:0)
这是因为它们共享相同的标识,即,它们指向相同的内存位置。我们的行为与列表相同
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