在 Python returns `TypeError, object not callable` 中用 __getattr__ 方法腌制对象
Pickle of object with __getattr__ method in Python returns `TypeError, object not callable`
我想用 __getattr__
方法为未知属性定义 class returns None
。
这样做之后,我试图将那个 class 的对象转储到 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
没有定义__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)
如果您重写 __getattr__
,您已经知道如何通过实施 __getstate__
和 __setstate__
方法
准确地腌制您的对象
查看 here 了解更多信息
>>> 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 会尝试检查您的对象是否具有 __getstate__
方法,该方法可用于自定义对象的 pickle 方式。因为您的 class 没有定义 __getstate__
方法,所以您的 __getattr__
方法最终被调用并且它 returns None
。 Pickle 尝试调用此 None
值并产生您遇到的异常。
有两种方法可以解决这个问题:
在你的 class:
中定义一个 __getstate__
和相应的 __setstate__
方法
def __getstate__(self):
return vars(self)
def __setstate__(self, state):
vars(self).update(state)
重写您的 __getattr__
方法以更好地处理 dunder-attributes(即抛出 AttributeError 而不是返回无意义的值):
def __getattr__(self, attr: str) -> Any:
"""Return None for all unknown attributes"""
if attr.startswith('__') and attr.endswith('__'):
raise AttributeError
return None
我想用 __getattr__
方法为未知属性定义 class returns None
。
这样做之后,我试图将那个 class 的对象转储到 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
没有定义__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)
如果您重写 __getattr__
,您已经知道如何通过实施 __getstate__
和 __setstate__
方法
查看 here 了解更多信息
>>> 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 会尝试检查您的对象是否具有 __getstate__
方法,该方法可用于自定义对象的 pickle 方式。因为您的 class 没有定义 __getstate__
方法,所以您的 __getattr__
方法最终被调用并且它 returns None
。 Pickle 尝试调用此 None
值并产生您遇到的异常。
有两种方法可以解决这个问题:
在你的 class:
中定义一个__getstate__
和相应的__setstate__
方法def __getstate__(self): return vars(self) def __setstate__(self, state): vars(self).update(state)
重写您的
__getattr__
方法以更好地处理 dunder-attributes(即抛出 AttributeError 而不是返回无意义的值):def __getattr__(self, attr: str) -> Any: """Return None for all unknown attributes""" if attr.startswith('__') and attr.endswith('__'): raise AttributeError return None