I don't understand the error message and also couldn't find other SO questions and answers helping me to understand this. The MWE is tested with Python 3.9.2. I'm aware that there is a slots=True
parameter in Pythons 3.10 dataclasses. But this isn't an option here.
The error output:
Traceback (most recent call last):
File "/home/user/dc.py", line 6, in <module>
class Foo:
ValueError: 'b' in __slots__ conflicts with class variable
Why does that happen? I even don't understand the background of that error.
#!/usr/bin/env pyhton3
from dataclasses import dataclass, field
@dataclass(init=False)
class Foo:
__slots__ = ('a', 'b')
a: int
b: list[str] = field(init=False)
def __init__(self, a, ccc):
self.a = a
# b = _some_fancy_modifications(ccc)
self.b = b
if __name__ == '__main__':
f = Foo(1, list('bar'))
The member b
is not given as an argument of __init__()
but computed based on the argument ccc
. Because of that I think I need to write my own __init__()
(@dataclass(init=False)
) and the b
member shouldn't be initialized by dataclass (field(init=False)
). Maybe I misunderstood something here?
For __slots__
to work, Python has to insert special descriptor objects into the class dict to manage attribute access. Otherwise, since the attributes aren't stored in the instance dict, attribute lookup would be completely unable to find your attributes. Descriptors tell the attribute lookup machinery how to find special attributes.
For the b
slot to work, Python has to insert a descriptor for that attribute corresponding to the 'b'
key in your class dict. But you've already put something there: the field
object you created. You can't have a field
object and a slot descriptor as values for the same key. Python recognizes that this is a problem, and raises an error to tell you that you need to do something about this.
This isn't really something you can fix on your end. __slots__
support for dataclasses needs changes to the dataclass machinery, changes that happened in 3.10. In 3.9, you're stuck not using slots with dataclasses.