如何腌制numpy ndarray派生类?

时间:2019-02-01 19:28:27

标签: python numpy multidimensional-array pickle

我腌制了一个从ndarray派生的类的实例,但是在腌制/解腌期间丢失了属性。下面是简化的代码来说明此问题。我不明白:

  1. 为什么酱菜堆放/装载中不包含“ attrib”?我必须怎么做才能将其包括在内?
  2. 为什么在转储期间不调用__getstate __()以便我可以添加丢失的“ atrrib”? __setstate __()被调用。如何设置状态?我的想法是我将“ attrib”添加到获得的状态,以便以后进行设置。
import numpy as np
import pickle

class Xndarray(np.ndarray):
    def __new__(cls, **kwargs):
        return super().__new__(cls, (5, 3), **kwargs)

    def __init__(self, **kwargs):
        self[...] = -1
        self.attrib = 0

    def add2getstate(self):
        print("add2getstate()", self.__dict__)   

    def __getstate__(self):                         # This never gets called
        print("__getstate__()")
        return super().__getstate__()

    def __setstate__(self, data):
        print("__setstate__()")
        super().__setstate__(data)


if __name__ == "__main__":
    fname = "fname.pkl"

    x = Xndarray()

    x[0] = 0
    x.attrib += 2

    print(x)
    x.add2getstate()
    print(x.attrib)

    with open(fname, "wb") as fh:
        pickle.dump(x, fh)

    print("---------------")

    with open(fname, "rb") as fh:
        y = pickle.load(fh)

    print(y)
    y.add2getstate()
    print(y.attrib)

以下是输出:

[[ 0.  0.  0.]
 [-1. -1. -1.]
 [-1. -1. -1.]
 [-1. -1. -1.]
 [-1. -1. -1.]]
add2getstate() {'attrib': 2}
2
---------------
__setstate__()
[[ 0.  0.  0.]
 [-1. -1. -1.]
 [-1. -1. -1.]
 [-1. -1. -1.]
 [-1. -1. -1.]]
add2getstate() {}
Traceback (most recent call last):
  File "./t.py", line 48, in <module>
    print(y.attrib)
AttributeError: 'Xndarray' object has no attribute 'attrib'

4 个答案:

答案 0 :(得分:1)

__getstate__如果对象使用默认仅称为__reduce__ / __reduce_ex__numpy.ndarray有自己的__reduce__实现不打电话给你__getstate__

numpy.ndarray.__reduce__仅包含其知道的对象数据,而不包含self.attrib,并且numpy.ndarray.__setstate__不知道如何设置self.attrib,即使您以某种方式包含了该属性。 / p>

您将需要实现自己的__reduce____setstate__和{手柄{1}}自己。

答案 1 :(得分:0)

我完全不知道您为什么实施__getstate__。 尝试删除__getstate__,然后它应该是完整的。

泡菜中没有self.attrib,因为您实现了自己的__getstate__并仅从继承的类中返回__getstate__

答案 2 :(得分:0)

使用莳萝代替泡菜https://pypi.org/project/dill/。作为莳萝泡菜从扩展接口几乎是一样的。

import dill
with open(fname, "wb") as fh:
    dill.dump(x,fh)

print("---------------")

with open(fname, "rb") as fh:
    y = dill.load(fh)

答案 3 :(得分:0)

Numpy数组不实现__getstate__,但是实现__reduce__。

请参见https://docs.python.org/2/library/pickle.html#pickling-and-unpickling-extension-types