分段酸洗和一次酸洗之间的区别?

时间:2018-12-16 00:32:15

标签: python serialization pickle

给出这样的任意pythonic对象:

class ExampleObj(object):
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        self.c = 'c'

obj = ExampleObj()

这两种序列化方法之间是否存在功能差异?

片状酸洗

base = type(obj)
name = obj.__class__.__name__
pickled_data = {}

for key,val in obj.__dict__.items():
    pickled_data[key] = pickle.dumps(val)

vars = {k : pickle.loads(v) for k,v in pickled_data.items()}
restored = type(name, (base,), vars)

标准酸洗

restored = pickle.loads( pickle.dumps(obj) )

我无法想象任何事情,但是我担心可能没有考虑一些极端情况。

(在我的应用程序中,某些对象可能没有可序列化的变量。我们希望实现分段酸洗,以便我们更好地识别哪些变量阻止我们酸洗对象)

1 个答案:

答案 0 :(得分:1)

在第一种情况下,您正在创建type的实例,而在第二种情况下,您正在创建类型为ExampleObj的实例。要查看两个结果在功能上的不同,我将第一个示例的结果命名为restored_1,第二个命名为restored_2

type(restored_1)  # type
type(restored_2)  # __main__.ExampleObj

因此,restored_1restored_2在功能上不等同于您所要查找的内容。

为简单起见,请向ExampleObj添加方法或属性,然后尝试以各种方式使用任一过程中的还原对象。

class ExampleObj(object):
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        self.c = 'c'

    def foo(self):
        print('bar')

    @property
    def baz(self):
        print(self.a + self.b)

obj = ExampleObj()

执行您的第一个代码后,它返回type的实例:

restored_1.foo()     # exception raised because restored_1 is not an ExampleObj instance
restored_1.bar       # returns <property at 0x107863138> type
restored_1.__dict__  # returns a mappingproxy object

执行完第二条代码后,该代码返回ExampleObj的实例:

restored_2.foo()     # bar
restored_2.bar       # ab
restored_2.__dict__  # {'a': 'a', 'b': 'b', 'c': 'c'}

如果您正在寻找有关解决哪些实例attrs酸洗失败的方法的讨论,请参见以下问题:How to tell for which object attribute pickle fails?