I would like to put __slots__
on a dataclass with fields with defaults. When I try do that, I get this error:
>>> @dataclass
... class C:
... __slots__ = ('x', 'y', )
... x: int
... y: int = 1
...
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: 'y' in __slots__ conflicts with class variable
Is there a way to achieve this?
As noted already in the answers, data classes from dataclasses cannot generate slots for the simple reason that slots must be defined before a class is created.
__slots__ is a class variable. If you have more than one instance of your class, any change made to __slots__ will show up in every instance. You cannot access the memory allocated by the __slots__ declaration by using subscription. You will get only what is currently stored in the list.
A dataclass can very well have regular instance and class methods. Dataclasses were introduced from Python version 3.7. For Python versions below 3.7, it has to be installed as a library.
DataClass in Python DataClasses are like normal classes in Python, but they have some basic functions like instantiation, comparing, and printing the classes already implemented. Parameters: init: If true __init__() method will be generated. repr: If true __repr__() method will be generated.
There is, by using the @add_slots decorator by ericvsmith:
import dataclasses
def add_slots(cls):
# Need to create a new class, since we can't set __slots__
# after a class has been created.
# Make sure __slots__ isn't already set.
if '__slots__' in cls.__dict__:
raise TypeError(f'{cls.__name__} already specifies __slots__')
# Create a new dict for our new class.
cls_dict = dict(cls.__dict__)
field_names = tuple(f.name for f in dataclasses.fields(cls))
cls_dict['__slots__'] = field_names
for field_name in field_names:
# Remove our attributes, if present. They'll still be
# available in _MARKER.
cls_dict.pop(field_name, None)
# Remove __dict__ itself.
cls_dict.pop('__dict__', None)
# And finally create the class.
qualname = getattr(cls, '__qualname__', None)
cls = type(cls)(cls.__name__, cls.__bases__, cls_dict)
if qualname is not None:
cls.__qualname__ = qualname
return cls
>>> @add_slots
... @dataclass
... class C:
... __slots__ = ('x', 'y', )
... x: int
... y: int = 1
Adding __slots__
manually works as long as there are no defaults. You can find related the Github issue here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With