为什么在__new__期间添加的属性信息在酸洗过程中丢失了?

时间:2019-02-18 07:27:32

标签: python python-3.x

我有一个float子类,定义如下:

class NewFloat(float):
    def __new__(cls, value, value2):
        r = super().__new__(cls, value)
        r.value = value2
        return r

当我创建此类的实例时,所有方法都工作良好-a = NewFloat(1, 2)给出了对象a,使得a.value返回2。但是,当我腌制对象(pickle.dump(a, open('file.p', 'wb')))并尝试加载它(pickle.load(open('file.p', 'rb')))时,它将引发以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-75-ff08f7f793b8> in <module>
----> 1 b = pickle.load(open('test_pickle.p', 'rb'))

TypeError: __new__() missing 1 required positional argument: 'value2'

在酸洗过程中导致此错误的原因是什么?再次致电__new__,为什么?

我发现在函数定义中添加属性可以正常工作,但是我看不出为什么这应该有所不同:

class NewFloat2(float):
    def save_value(self, value):
        r.value = value

可以对NewFloat2实例进行腌制和加载,没问题。任何见识将不胜感激!

1 个答案:

答案 0 :(得分:0)

通常,在酸洗时,将保存obj.__classobj.__dict__,并在进行酸洗时执行cls.__new__(cls)cls.__dict__.update(attrs)

也就是说,pickle不会在默认情况下取消拾取时将多余的args传递给您的__new__()方法。为了解决这个问题,您必须在类中定义__getnewargs__()方法,以告诉pickle传递这些参数,例如:

class NewFloat(float):
    def __new__(cls, value, value2):
        r = super().__new__(cls, value)
        r.value = value2
        r.original_value = value
        return r
    def __getnewargs__(self):
        return (self.original_value,self.value)

然后pickle会根据需要显示。如果您也想传递关键字args,则可以定义__getnewargs_ex__()方法,

请注意,在这样的示例中,value参数在实例中是无用的且未保存。在普通应用程序中,您可以将其保存在实例的属性中或将其删除。