在 pickle-able 类中实现什么神奇的方法?

问题描述 投票:0回答:0

Class Sketch(dict) 重构(unpickle)错误(见下面的代码):

Failed example:
    s2 = pickle.loads(b)
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.9/doctest.py", line 1336, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest __main__[10]>", line 1, in <module>
        s2 = pickle.loads(b)
      File "/home/vlz/Documents/py31eg/image/pickle_lab.py", line 66, in __setitem__
        if color != self.background:
    AttributeError: 'Sketch' object has no attribute 'background'
**********************************************************************
1 items had failures:
   1 of  12 in __main__
***Test Failed*** 1 failures.

这就是我开始的地方。他的对手 Sketch_has_dict(object) pickle/unpickle -ed 成功(在下面的同一测试中)。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
>>> s = Sketch_has_dict()
>>> for y in range(2):
...     for x in range(3):
...             s[(x, y)] = 'yellow'
...
>>> import pickle
>>> b = pickle.dumps(s, protocol=pickle.HIGHEST_PROTOCOL)
>>> s2 = pickle.loads(b)
>>> len(s2)
6
>>> s = Sketch()
>>> for y in range(2):
...     for x in range(3):
...             s[(x, y)] = 'yellow'
...
>>> import pickle
>>> b = pickle.dumps(s, protocol=pickle.HIGHEST_PROTOCOL)
>>> s2 = pickle.loads(b)
>>> len(s2)
6
"""


class Sketch_has_dict:
    def __init__(self, width=3, height=2, background='red'):
        self.color = set()
        self.width = width
        self.height = height
        self.background = background
        self.pixels = {}

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

    def __getitem__(self, coord):
        return self.pixels.get(coord, self.background)

    def __setitem__(self, coord, color):
        if color != self.background:
            self.pixels[coord] = color

    def __repr__(self):
        return repr(self.pixels)


class Sketch(dict):
    def __new__(cls):
        s = super().__new__(cls)
        s.colors = set()
        s.width = 3
        s.height = 2
        s.background = 'red'
        return s

    def __init__(self, width=3, height=2, background='red'):
        self.colors = set()
        self.width = width
        self.background = background
        self.height = height
        super(Sketch, self).__init__()

    def __setitem__(self, coord, color=None):
        if color != self.background:
            self.colors.add(color)
        super(Sketch, self).__setitem__(coord, color)


if __name__ == '__main__':
    import doctest
    doctest.testmod()

当我将 __new__ 方法添加到 Sketch(dict) 类时,测试通过了。我硬编码了初始 attr 值。我不清楚在重构对象时何时以及使用什么参数调用 __new__ 。

当我需要 pickle-able 类时,我应该实现什么神奇的方法?看起来 __init__ 在重构(pickle.loads)两个实例时没有被调用。重构对象时 pickle.loads() 的步骤是什么?

使用 Python 3.9.2,Debian GNU/Linux 11(靶心)

附言 我重读了我的问题。听起来不清楚。换句话说:我应该如何重构我的 Sketch 类以使其适合 pickle.dumps、pickle.loads?

python-3.x pickle
© www.soinside.com 2019 - 2024. All rights reserved.