mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
If using a frozen class with slots, add __getstate__ and __setstate__ to set the instance values. (GH-25786)
This commit is contained in:
parent
f82fd77717
commit
823fbf4e0e
2 changed files with 34 additions and 2 deletions
|
@ -1087,14 +1087,28 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
|
|||
tuple(f.name for f in std_init_fields))
|
||||
|
||||
if slots:
|
||||
cls = _add_slots(cls)
|
||||
cls = _add_slots(cls, frozen)
|
||||
|
||||
abc.update_abstractmethods(cls)
|
||||
|
||||
return cls
|
||||
|
||||
|
||||
def _add_slots(cls):
|
||||
# _dataclass_getstate and _dataclass_setstate are needed for pickling frozen
|
||||
# classes with slots. These could be slighly more performant if we generated
|
||||
# the code instead of iterating over fields. But that can be a project for
|
||||
# another day, if performance becomes an issue.
|
||||
def _dataclass_getstate(self):
|
||||
return [getattr(self, f.name) for f in fields(self)]
|
||||
|
||||
|
||||
def _dataclass_setstate(self, state):
|
||||
for field, value in zip(fields(self), state):
|
||||
# use setattr because dataclass may be frozen
|
||||
object.__setattr__(self, field.name, value)
|
||||
|
||||
|
||||
def _add_slots(cls, is_frozen):
|
||||
# Need to create a new class, since we can't set __slots__
|
||||
# after a class has been created.
|
||||
|
||||
|
@ -1120,6 +1134,11 @@ def _add_slots(cls):
|
|||
if qualname is not None:
|
||||
cls.__qualname__ = qualname
|
||||
|
||||
if is_frozen:
|
||||
# Need this for pickling frozen classes with slots.
|
||||
cls.__getstate__ = _dataclass_getstate
|
||||
cls.__setstate__ = _dataclass_setstate
|
||||
|
||||
return cls
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue