【问题标题】:pickle object with overloaded __new__具有重载的 __new__ 的泡菜对象
【发布时间】:2019-06-22 00:32:39
【问题描述】:

在我的程序中,我使用从不可变对象类(命名元组)派生的类。我之所以选择这样做,是因为元组似乎会导致磁盘上文件的大小明显变小(一开始我没有检查它们的可加载性。)此外,还有几个静态常量对象正在使用中。根据输入 __new__ 可以中止计算并改为返回静态对象之一。

我已经覆盖了__new__ 方法。 __new__ 采用的参数少于字段数量,并进行非平凡的计算以获得其他字段的值。当我尝试解开类的对象时,__new__ 方法会以不应该的方式被调用。下面的示例是问题的剥离版本。

例子:

import pickle

class testclass(tuple):
     def __new__(cls,x):
         assert type(x)==int, "Wrong input type to constructor"
         return super().__new__(cls,[x,x*2,x**2])

pickle.loads(pickle.dumps( testclass(4),protocol = -1))

输出:

断言错误

如何使用自定义构造函数创建也可序列化的元组对象?


扩展示例。初始计算耗时且不可逆:

import pickle, time

class testclass(tuple):
     def __new__(cls,params):
         assert type(params)==dict, "Wrong input type to constructor"
         a = params['sec']
         p,g = 23, 5
         r = p**a % g
         time.sleep(params['wait'])
         return super().__new__(cls,[p,g,r])

pickle.loads(pickle.dumps( testclass({'sec':4,'wait':1}),protocol = -1))

【问题讨论】:

    标签: python python-3.x class pickle


    【解决方案1】:

    您可以通过为pickle 定义一个__getnewargs__() 方法来使用:

    import pickle
    
    
    class Testclass(tuple):
        def __new__(cls, x):
            assert isinstance(x, int), "Wrong input type to constructor"
            return super().__new__(cls, (x, x*2, x**2))
    
        def __getnewargs__(self):
            return (self[0],)  # Just return first element of sequence.
    
    
    pickle.loads(pickle.dumps(Testclass(4), protocol=-1))
    

    【讨论】:

    • 对,这只是因为最小示例的特别简单。如果self[0] 不等于输入怎么办?
    • @Dimitry:在这种情况下,我建议您的最小示例太多了。请编辑您的问题并提供重现问题的内容。
    【解决方案2】:

    嗯,最后,我得到的答案是“不要用重载的__new__ 腌制对象”。

    import pickle, time
    class Testclass(tuple):
         @classmethod 
         def new(cls,params):
             a = params['sec']
             p,g = 23, 5
             r = p**a % g
             time.sleep(params['wait'])
             return cls([p,g,r])
    
    pickle.loads(pickle.dumps( Testclass.new({'sec':4,'wait':1}),protocol = -1))
    

    在我的代码中,我可以将所有对构造函数的调用替换为显式函数调用。然后将创建\unpickling 留给默认构造函数,它们除了设置字段之外没有做太多事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多