在 Python 中使用 __getattr__ 方法对对象进行 Pickle 返回 `TypeError, object not callable`

Jea*_* T. 1 python pickle python-3.x

我想定义一个None__getattr__方法返回未知属性的类。

这样做之后,我试图将该类的对象转储到 Pickle。

但是,我得到了错误

Traceback (most recent call last):
  File "c:\SVN\Scripts\Rally\examples\t_pickle_None.py", line 14, in <module>
    pickle.dump(toto, f, pickle.HIGHEST_PROTOCOL)
TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)

没有定义__getattr__,它工作正常,但我想保留这个功能。

这是我的代码:如何使其工作__getattr__

谢谢

import pickle
from typing import Any

class Toto:
    def __init__(self, name:str) -> None:
        self.name = name

    def __getattr__(self, _: str) -> Any:
        """Return None for all unknown attributes"""
        return None

toto = Toto("Toto")
with open('toto.pkl', 'wb') as f:
    pickle.dump(toto, f, pickle.HIGHEST_PROTOCOL)
Run Code Online (Sandbox Code Playgroud)

Ara*_*Fey 5

问题在于pickle 会尝试检查您的对象是否有一个__getstate__方法,该方法可用于自定义对象的pickle 方式。因为您的类没有定义__getstate__方法,所以您的__getattr__方法最终会被调用并返回None. Pickle 尝试调用此None值并产生您得到的异常。

有两种方法可以解决这个问题:

  1. 在你的类中定义一个__getstate__和相应的__setstate__方法:

    def __getstate__(self):
        return vars(self)
    
    def __setstate__(self, state):
        vars(self).update(state)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 重写您的__getattr__方法以更好地处理 dunder 属性(即抛出 AttributeError 而不是返回无意义的值):

    def __getattr__(self, attr: str) -> Any:
        """Return None for all unknown attributes"""
        if attr.startswith('__') and attr.endswith('__'):
            raise AttributeError
        return None
    
    Run Code Online (Sandbox Code Playgroud)