【问题标题】:Self unpickling in class method in pythonpython中类方法中的自解包
【发布时间】:2018-10-17 11:25:41
【问题描述】:

我正在尝试创建一个可以使用类方法序列化和反序列化自身的对象,而不使用 return 语句(我不想要静态方法)。这是我的类的一个概念和一个幼稚的用例:

import pickle

class A:
    def __init__(self):
        self.x = 0

    def add(self):
        self.x += 1

    def serialize(self, filename):
        """Simple object serialization given a filename"""
        with open(filename, 'wb') as f:
            pickle.dump(self, f)
            print("Serialized with value of: %d" % (self.x))

    def deserialize(self, filename):
        """Simple object deserialization given a filename"""
        with open(filename, 'rb') as f:
            print("self.x before load (inside deserialize): %d" % (self.x))
            self = pickle.load(f)
            print("Deserialized value inside deserialize function: %d" % (self.x))



a1 = A()
a2 = A()

a1.add()
a1.add()

a1.serialize('a.pkl')
a2.deserialize('a.pkl')

print("Deserialized value outside: %d" % (a2.x))

但是,一旦我离开反序列化方法,self(在本例中为实例a2)就不会保持其值。

运行时的输出:

>> Serialized with value of: 2
>> self.x before load (inside deserialize): 0
>> Deserialized value inside deserialize function: 2
>> Deserialized value outside: 0

为什么会这样?我也尝试在函数deserialize 中的pickle.load 之后使用deepcopy,但似乎没有任何效果,我想了解原因。

提前致谢

【问题讨论】:

  • 您需要更多的功能才能完成这项工作。否则,您只是在转储类构造函数的内存,而不是所述类的实例(如果我没记错的话):docs.python.org/3/library/pickle.html#pickling-class-instances。可以在这里找到对实例变量和类变量之间区别的一个很好的解释:stackoverflow.com/questions/10842553/pickle-with-custom-classes
  • 首先请避免self = pickle.load(f),然后在deserialize 方法中而不是输出读取值,您只是要求它打印self.x,这对我来说似乎是错误的。
  • @Torxed 我已经看过了,但他的问题是空变量是类变量,而不是实例变量。就我而言,反序列化后,未更改的变量是实例变量
  • 那是因为你没有调用适当的内置函数__update__等。也就是说,如果你真的不想要下面解决方案中提到的返回函数。

标签: python deserialization self


【解决方案1】:

这不起作用的原因是因为你不能分配给自己(或者更确切地说:这样做并没有按照你的想法做)。如果您有兴趣了解实际发生的情况,请尝试将一些奇怪的东西分配给 self,例如self = "foobar"(行为将保持不变)。


deserialize 设为类方法并将其用作“构造函数”:

@classmethod
def deserialize(cls, filename):
    """Simple object deserialization given a filename"""
    with open(filename, 'rb') as f:
        obj = pickle.load(f)
        print("Deserialized value inside deserialize function: %d" % (obj.x))
        return obj

然后像这样使用它:

a2 = A.deserialize('a.pkl')

输出:

序列化,值为:2
反序列化函数内的反序列化值:2
外面的反序列化值:2

【讨论】:

【解决方案2】:

抱歉回复晚了。 Pickle 将对象展平为字典。 这是修复它的方法:

    def serialize(self, filename):
        """Simple object serialization given a filename"""
        with open(filename, 'wb') as f:
            pickle.dump(self.__dict__, f)
            print("Serialized with value of: %d" % (self.x))

    def deserialize(self, filename):
        """Simple object deserialization given a filename"""
        with open(filename, 'rb') as f:
            print("self.x before load (inside deserialize): %d" % (self.x))
            self.__dict__ = pickle.load(f)
            print("Deserialized value inside deserialize function: %d" % (self.x))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 2021-07-14
    • 2017-08-25
    相关资源
    最近更新 更多