Search code examples
pythonpython-3.xpython-dataclasses

Python, why is the dataclass attribute read-only?


I have a dataclass which its signature gets updated based on the active configs before it gets initiated and may be modified after initiation. Accordingly, I have something like this:


from dataclasses import dataclass, field


@dataclass(slots=True, frozen=False)
class MyClass:
    att_1: str = field(init=False)
    att_2: str = field(init=False)

    @classmethod
    def update_class(cls, first, second):
        cls.att_1 = first
        cls.att_2 = second

My problem is that although the dataclass is not frozen, when I initiate the class I cannot change the attributes anymore. This is a sample of what I do.


MyClass.update_class("11", "12")
print(MyClass.att_1)
a = MyClass()

print(a)
print(MyClass.att_2)
print(MyClass.att_1)
a.att_2 = "002"
print(a)

Running this I get what is shown bellow:


11
MyClass(att_1='11', att_2='12')
12
11
Traceback (most recent call last):
  File "/b.py", line 25, in <module>
    a.att_2 = "002"
AttributeError: 'MyClass' object attribute 'att_2' is read-only

Can someone tell me why is att_2 read-only and how can I fix this?


Solution

  • So, the problem is that you are using __slots__ and then removing the __slots__ descriptors, breaking your class. So, consider (without the dataclass involved):

    >>> class Foo:
    ...     __slots__ = "x", "y"
    ...
    >>> foo = Foo()
    >>> foo.x = 1
    >>> foo.x
    1
    >>> Foo.x
    <member 'x' of 'Foo' objects>
    >>> Foo.x = None
    >>> foo.x
    >>> foo.x = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Foo' object attribute 'x' is read-only
    

    So, one simple solution is to not use __slots__, but it really isn't clear to me how this is all supposed to work or why you have an update_class method (and what it's supposed to accomplish).