我有一个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
实例进行腌制和加载,没问题。任何见识将不胜感激!
答案 0 :(得分:0)
通常,在酸洗时,将保存obj.__class
和obj.__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
参数在实例中是无用的且未保存。在普通应用程序中,您可以将其保存在实例的属性中或将其删除。