There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().
import pickle
from dataclasses import dataclass
@dataclass(frozen=True)
class A:
__slots__ = ('a',)
a: int
def __getstate__(self):
return dict(
(slot, getattr(self, slot))
for slot in self.__slots__
if hasattr(self, slot)
)
def __setstate__(self, state):
for slot, value in state.items():
object.__setattr__(self, slot, value) # <- use object.__setattr__
b = pickle.dumps(A(5))
pickle.loads(b)
问题来自
pickle
在设置插槽状态时使用实例的__setattr__
方法。在默认的} line 6220 中的
__setstate__
是在^{load_build
中定义的。在对于状态dict中的项,实例
__dict__
直接更新:而对于slotstate dict中的项,则使用实例的
^{pr2}$__setattr__
:现在,由于实例被冻结,}。在
__setattr__
在加载时引发{为了避免这种情况,您可以定义自己的
__setstate__
方法,它将使用object.__setattr__
,而不是实例的__setattr__
。在docs对此给出了某种警告:
将},这可能也是一个好的选择。否则,
__getstate__
定义为实例__dict__
在您的例子中始终是{__setstate__
的state
参数将是一个元组(None, {'a': 5})
,第一个值是实例的__dict__
的值,第二个值是slotstate dict我个人不会说它是一个bug,因为酸洗过程的设计是灵活的,但是还有一些功能增强的空间。对酸洗规程的修订可以在将来解决这个问题。除非我遗漏了一些东西,并且除了性能损失之外,对所有插槽使用
PyObject_GenericSetattr
可能是一个合理的解决方案?在相关问题 更多 >
编程相关推荐