Как засолить нудистый ndarray производный класс? - PullRequest
0 голосов
/ 01 февраля 2019

Я выбрал экземпляр класса, производного от 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 голосов
/ 02 февраля 2019

__getstate__ вызывается, только если ваш объект использует значение по умолчанию __reduce__ / __reduce_ex__.numpy.ndarray имеет свою собственную реализацию __reduce__, которая не вызывает ваш __getstate__.

numpy.ndarray.__reduce__ включает только данные объекта, о которых он знает, но не self.attrib, и numpy.ndarray.__setstate__ не знает, какустановить self.attrib, даже если вы как-то включили этот атрибут.

Вам нужно будет реализовать свои собственные __reduce__ и __setstate__ и обрабатывать self.attrib самостоятельно.

0 голосов
/ 01 февраля 2019

Используйте укроп вместо маринада 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)
0 голосов
/ 02 февраля 2019

Массивы Numpy не реализуют __getstate__, но __reduce__.

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

0 голосов
/ 01 февраля 2019

Я не знаю, почему вы реализовали __getstate__ вообще.Попробуйте удалить __getstate__, и тогда оно должно быть завершено.

В рассоле нет self.attrib, потому что вы реализуете свой собственный __getstate__ и возвращаете только __getstate__ из класса, который вы наследуете.

...