将pickle-able属性添加到numpy.ndarray的子​​类中

时间:2018-05-17 04:45:27

标签: python-3.x numpy pickle

我想将属性(.csys)添加到numpy.ndarray的子​​类中:

import numpy as np

class Point(np.ndarray):

    def __new__(cls, arr, csys=None):
        obj = np.asarray(arr, dtype=np.float64).view(cls)
        obj._csys = csys
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self._csys = getattr(obj, '_csys', None)

    @property
    def csys(self):
        print('Getting .csys')
        return self._csys

    @csys.setter
    def csys(self, csys):
        print('Setting .csys')
        self._csys = csys

但是,当我运行此测试代码时:

pt = Point([1, 2, 3])
pt.csys = 'cmm'
print("pt.csys:", pt.csys)

# Pickle, un-pickle, and check again
import pickle

pklstr = pickle.dumps(pt)
ppt = pickle.loads(pklstr)

print("ppt.csys:", ppt.csys)

似乎无法对该属性进行腌制:

Setting .csys
Getting .csys
pt.csys: cmm
Getting .csys
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
C:\Rut\Vanes\bin\pointtest.py in <module>()
     39     ppt = pickle.loads(pklstr)
     40 
---> 41     print("ppt.csys:", ppt.csys)

C:\Rut\Vanes\bin\point.py in csys(self)
     15     def csys(self):
     16         print('Getting .csys')
---> 17         return self._csys
     18 
     19     @csys.setter

AttributeError: 'Point' object has no attribute '_csys'

我尝试在不使用装饰器的情况下做同样的事情(例如定义get_csys()set_csys(),加上csys = property(__get_csys, __set_csys),但结果与此相同。

我在Python 3.6.3下使用numpy 1.13.3

1 个答案:

答案 0 :(得分:0)

这个问题已经被问及并回答here。简而言之,numpy使用__reduce____setstage__来腌制自己。适用于上述情况的覆盖内容如下所示:

def __reduce__(self):
    # Get the parent's __reduce__ tuple
    pickled_state = super().__reduce__()
    # Create our own tuple to pass to __setstate__
    new_state = pickled_state[2] + (self._csys,)
    # Return a tuple that replaces the parent's __setstate__ tuple with our own
    return (pickled_state[0], pickled_state[1], new_state)

def __setstate__(self, state):
    self._csys = state[-1]  # Set the _csys attribute
    # Call the parent's __setstate__ with the other tuple elements.
    super().__setstate__(state[0:-1])

另请注意,在这种简单的情况下,并不严格要求getter和setter方法(分别在@property@csys.getter装饰器下)。如果免除这些费用,请直接访问.csys,而不是通过“私人”访问._csys.wrapper { background-color: #f1f1f1; height: 300px; width: 50%; margin: 0 auto; display: table; } .innerWrapper { display: table-cell; vertical-align: middle; text-align: center; width: fit-content; } .box { display: inline-block; padding: 25px 25px; opacity: 0.8; background-color: #32CD32; }属性。