如何腌制派生的 numpy ndarray class?

How to pickle numpy ndarray derived class?

我腌制了派生自 ndarray 的 class 实例,但在 pickling/unpickling 期间丢失了属性。下面是用于说明问题的简化代码。我不明白:

  1. 为什么 "attrib" 不包含在 pickle dump/load 中?我必须做什么才能包含在内?
  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'

我完全不知道你为什么实施 __getstate__。 尝试删除 __getstate__ 然后它应该完成。

pickle 中没有 self.attrib,因为您实现了自己的 __getstate__ 和 return 只是继承自 class 的 __getstate__

用莳萝代替泡菜https://pypi.org/project/dill/。由于 dill 从 pickle 扩展而来,界面几乎是相同的。

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

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

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

Numpy 数组不实现 __getstate__ 但 __reduce__ .

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

__getstate__ 仅当您的对象使用默认值 __reduce__/__reduce_ex__ 时才会调用。 numpy.ndarray 有自己的 __reduce__ 实现,不会调用您的 __getstate__.

numpy.ndarray.__reduce__ 只包含它知道的对象数据,而不是 self.attrib,并且 numpy.ndarray.__setstate__ 不知道如何设置 self.attrib 即使你以某种方式包含该属性.

您需要实现自己的 __reduce____setstate__ 并自行处理 self.attrib