Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中使用_getattr__方法对对象进行Pickle,返回`TypeError,对象不可调用`_Python_Python 3.x_Pickle - Fatal编程技术网

Python中使用_getattr__方法对对象进行Pickle,返回`TypeError,对象不可调用`

Python中使用_getattr__方法对对象进行Pickle,返回`TypeError,对象不可调用`,python,python-3.x,pickle,Python,Python 3.x,Pickle,我想用\uu getattr\uuu方法定义一个类,该类为未知属性返回None 完成后,我尝试将该类的对象转储到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) TypeErro

我想用
\uu getattr\uuu
方法定义一个类,该类为未知属性返回
None

完成后,我尝试将该类的对象转储到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

如果重写
\uuuuuuGetAttr\uuuuuuuuuuu
,则通过实现
\uuuuuuuGetState\uuuuuuuuuu
\uuuuuuuuSetState\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>方法,您已经知道了对象可以被pickl

查看以获取更多信息

>>> import pickle
>>> class Toto:
...     def __init__(self, name:str):
...         self.name = name
...     def __getattr__(self, _: str):
...         """Return None for all unknown attributes"""
...         return None
...     def __getstate__(self): return self.__dict__
...     def __setstate__(self, d): self.__dict__.update(d)
... 
>>> 
>>> t=Toto()
>>> pickle.dumps(t)
b'\x80\x03c__main__\nToto\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00abcq\x04sb.'
>>> 

如果重写
\uuuuuuGetAttr\uuuuuuuuuuu
,则通过实现
\uuuuuuuGetState\uuuuuuuuuu
\uuuuuuuuSetState\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>方法,您已经知道了对象可以被pickl

查看以获取更多信息

>>> import pickle
>>> class Toto:
...     def __init__(self, name:str):
...         self.name = name
...     def __getattr__(self, _: str):
...         """Return None for all unknown attributes"""
...         return None
...     def __getstate__(self): return self.__dict__
...     def __setstate__(self, d): self.__dict__.update(d)
... 
>>> 
>>> t=Toto()
>>> pickle.dumps(t)
b'\x80\x03c__main__\nToto\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00abcq\x04sb.'
>>> 

问题是pickle试图检查对象是否有方法,该方法可用于自定义对象的pickle方式。因为您的类没有定义
\uuuuu getstate\uuuu
方法,所以您的
\uuuuuu getattr\uuuuu
方法最终被调用并返回
None
。Pickle尝试调用这个
None
值,这将生成您得到的异常

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

  • 在类中定义
    \uuuuu getstate\uuuuu
    和相应的
    \uuuu setstate\uuuuuu
    方法:

    def __getstate__(self):
        return vars(self)
    
    def __setstate__(self, state):
        vars(self).update(state)
    
  • 重写
    \uuu getattr\uuu
    方法以更好地处理dunder属性(即抛出AttributeError而不是返回无意义的值):


  • 问题是pickle试图检查对象是否有方法,该方法可用于自定义对象的pickle方式。因为您的类没有定义
    \uuuuu getstate\uuuu
    方法,所以您的
    \uuuuuu getattr\uuuuu
    方法最终被调用并返回
    None
    。Pickle尝试调用这个
    None
    值,这将生成您得到的异常

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

  • 在类中定义
    \uuuuu getstate\uuuuu
    和相应的
    \uuuu setstate\uuuuuu
    方法:

    def __getstate__(self):
        return vars(self)
    
    def __setstate__(self, state):
        vars(self).update(state)
    
  • 重写
    \uuu getattr\uuu
    方法以更好地处理dunder属性(即抛出AttributeError而不是返回无意义的值):


  • 您需要小心地酸洗定义
    \uuu getattr\uuuu
    的对象。我写了一些关于它的东西。这有帮助吗?也可以看看那里的链接。@PM2Ring interstating share,虽然Aran Fey的答案看起来更清楚(特别是在午夜半闭着眼睛的时候:)谢谢我同意Aran Fey的答案是好的,事实上我已经投了更高的票。:)但我认为这些链接有很好的相关信息,即使它们没有完全回答你的问题。如果他们真的回答了你的问题,那么我会将其作为副本关闭。:)的确我喜欢你的
    UserDict
    。我试图解决另一个问题,即
    mypy
    抱怨动态创建的输出,但
    mypy
    也抱怨您的代码:)。。。但这是另一天的话题(或者更具体地说是另一个问题)。您需要小心地清理定义
    \uuuu getattr\uuuu
    的对象。我写了一些关于它的东西。这有帮助吗?也可以看看那里的链接。@PM2Ring interstating share,虽然Aran Fey的答案看起来更清楚(特别是在午夜半闭着眼睛的时候:)谢谢我同意Aran Fey的答案是好的,事实上我已经投了更高的票。:)但我认为这些链接有很好的相关信息,即使它们没有完全回答你的问题。如果他们真的回答了你的问题,那么我会将其作为副本关闭。:)的确我喜欢你的
    UserDict
    。我试图解决另一个问题,即
    mypy
    抱怨动态创建的输出,但
    mypy
    也抱怨您的代码:)。。。但这是另一天的话题(或者更具体地说是另一个问题)。