Josh Rosenberg <[email protected]> added the comment:
You're right that in non-dataclass scenarios, you'd just use __slots__.
The slots=True thing was necessary for any case where any of the dataclass's
attributes have default values (my_int: int = 0), or are defined with fields
(my_list: list = field(default_factory=list)). The problem is that __slots__ is
implemented by, after the class definition ends, creating descriptors on the
class to access the data stored at known offsets in the underlying PyObject
structure. Those descriptors themselves being class attributes means that when
the type definition machinery tries to use __slots__ to create them, it finds
conflicting class attributes (the defaults/fields) that already exist and
explodes.
Adding support for slots=True means it does two things:
1. It completely defines the class without slots, extracts the stuff it needs
to make the dataclass separately, then deletes it from the class definition
namespace and makes a *new* class with __slots__ defined (so no conflict occurs)
2. It checks if the dataclass is also frozen, and applies alternate
__getstate__/__setstate__ methods that are compatible with a frozen, slotted
dataclass
#2 is what fixes this bug (while #1 makes it possible to use the full range of
dataclass features without sacrificing the ability to use __slots__). If you
need this to work in 3.9, you could borrow the 3.10 implementations that make
this work for frozen dataclasses to explicitly define __getstate__/__setstate__
for your frozen slotted dataclasses:
def __getstate__(self):
return [getattr(self, f.name) for f in fields(self)]
def __setstate__(self, state):
for field, value in zip(fields(self), state):
# use setattr because dataclass may be frozen
object.__setattr__(self, field.name, value)
I'm not closing this since backporting just the fix for frozen slotted
dataclasses (without backporting the full slots=True functionality that's a new
feature) is possibly within scope for a bugfix release of 3.9 (it wouldn't
change the behavior of working code, and fixes broken code that might
reasonably be expected to work).
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue45520>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com