Numpy array serialization unexpected behavior

code

Suppose I have:

import numpy
import pickle


class Test():
    def __init__(self):
        self.base = numpy.zeros(6)
        self.view = self.base[-3:]

    def __len__(self):
        return len(self.view)

    def update(self):
        self.view[0] += 1

    def add(self):
        self.view = self.base[-len(self.view) - 1:]
        self.view[0] = 1

    def __repr__(self):
        return str(self.view)


def serialize_data():
    data = Test()
    return pickle.dumps(data)

Note that a class Testis just a class containing a viewNumPy array base. This viewis just a slice of the last elements Nin the database ( N == 3during initialization).

Testhas a method update()that adds 1to the value in the 0view position and a method add()that resizes the view ( N = N + 1) and sets the value 0to 1.

The function serialize_datasimply instantiates Test()and then returns the serialized object with pickle.

Behavior

update , add - , , :

# Local variable
test = Test()
print(test)    # [ 0.  0.  0.]

test.update()
test.update()
print(test)    # [ 2.  0.  0.]

test.add()
print(test)    # [ 1.  2.  0.  0.]

, , add 2 ( update ) :

# Serialized variable
data = pickle.loads(serialize_data())
print(data)    # [ 0.  0.  0.]

data.update()
data.update()
print(data)    # [ 2.  0.  0.]

data.add()
print(data)    # [ 1.  0.  0.  0.]  <----  This should be [ 1. 2. 0. 0. ] !!!

?

+4
1

, / , . . , , , .

, __getstate__ __setstate__ , .

, . , . , .

class Test():
    def __init__(self):
        self.base = numpy.zeros(6)
        self.slice = slice(-3, self.base.size)
        self.view = self.base[self.slice]

    def __len__(self):
        return len(self.view)

    def update(self):
        self.view[0] += 1

    def add(self):
        self.slice = slice(-len(self.view) - 1, self.base.size)
        self.view = self.base[self.slice]        
        self.view[0] = 1

    def __getstate__(self):
        return {'base': self.base, 'slice': self.slice}

    def __setstate__(self, state):
        self.base = state['base']
        self.slice = state['slice']
        self.view = self.base[self.slice]

    def __repr__(self):
        return str(self.view)
+2

Source: https://habr.com/ru/post/1626992/


All Articles