【问题标题】:AttributeError while unpickling a subclass of dict取消 dict 的子类时出现 AttributeError
【发布时间】:2019-02-15 10:36:38
【问题描述】:

在 Python 3.5 中,我创建了一个非常简单的 dict 子类,它使用同义键(存储为字典属性):

class synonymDict(dict):

    def __init__(self, synonyms=None, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.synonyms = {} if synonyms is None else synonyms

    def __getitem__(self, name):
        return dict.__getitem__(self, self.synonyms.get(name, name))

    def __setitem__(self, name, value):
        dict.__setitem__(self, self.synonyms.get(name, name), value)

    def __repr__(self):
        return 'synonymDict(%s)' % dict.__repr__(self)

现在,假设我在myPackage.myTools 中定义了这个类; 我尝试了酸洗和解酸(用于多处理),但出现以下属性错误:

>>> from myPackage import myTools
>>> synonyms = dict(A='a', B='b')
>>> mymapped = myTools.synonymDict(synonyms)
>>> mymapped['A'] = 36
>>> mymapped
synonymDict({'a': 36})
>>> mymapped.synonyms
{'A': 'a', 'B': 'b'}
>>> import pickle
>>> pickle.loads(pickle.dumps(mymapped))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/users/ldog/glouvel/install/python3/LibsDyogen/myPhylTree.py", line 35, in __setitem__
    dict.__setitem__(self, self.synonyms.get(name, name), value)
AttributeError: 'synonymDict' object has no attribute 'synonyms'

为什么在解压过程中会出现这个错误?我应该制作synonyms 的深拷贝吗?是子类化问题还是命名空间问题?

【问题讨论】:

  • 我认为这回答了我的问题:stackoverflow.com/a/46560454/4614641>.

标签: python pickle subclassing


【解决方案1】:

根据这个答案https://stackoverflow.com/a/46560454/4614641,我可以用一行来解决我的问题:定义一个默认的synonyms class 属性。

新代码:

class synonymDict(dict):
    synonyms = {}  # Needed for unpickling!

    def __init__(self, synonyms=None, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.synonyms = {} if synonyms is None else synonyms

    def __getitem__(self, name):
        return dict.__getitem__(self, self.synonyms.get(name, name))

    def __setitem__(self, name, value):
        dict.__setitem__(self, self.synonyms.get(name, name), value)

    def __repr__(self):
        return 'synonymDict(%s)' % dict.__repr__(self)

这是因为unpickling(见https://docs.python.org/3.5/library/pickle.html#pickling-class-instances)没有调用类的__init__方法,而是尝试调用__setitem__首先!我已经覆盖了它来调用一个只在__init__中定义的属性...

【讨论】:

    猜你喜欢
    • 2021-02-15
    • 2019-05-24
    • 1970-01-01
    • 2020-05-26
    • 2017-11-28
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    相关资源
    最近更新 更多