[Python-Dev] Should the dataclass frozen property apply to subclasses?
Eric V. Smith
eric at trueblade.com
Thu Feb 22 05:55:07 EST 2018
On 2/22/2018 1:56 AM, Raymond Hettinger wrote:
> When working on the docs for dataclasses, something unexpected came up. If a dataclass is specified to be frozen, that characteristic is inherited by subclasses which prevents them from assigning additional attributes:
>
> >>> @dataclass(frozen=True)
> class D:
> x: int = 10
>
> >>> class S(D):
> pass
>
> >>> s = S()
> >>> s.cached = True
> Traceback (most recent call last):
> File "<pyshell#49>", line 1, in <module>
> s.cached = True
> File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/dataclasses.py", line 448, in _frozen_setattr
> raise FrozenInstanceError(f'cannot assign to field {name!r}')
> dataclasses.FrozenInstanceError: cannot assign to field 'cached'
This is because "frozen-ness" is implemented by adding __setattr__ and
__delattr__ methods in D, which get inherited by S.
> Other immutable classes in Python don't behave the same way:
>
>
> >>> class T(tuple):
> pass
>
> >>> t = T([10, 20, 30])
> >>> t.cached = True
>
> >>> class F(frozenset):
> pass
>
> >>> f = F([10, 20, 30])
> >>> f.cached = True
>
> >>> class B(bytes):
> pass
>
> >>> b = B()
> >>> b.cached = True
The only way I can think of emulating this is checking in __setattr__ to
see if the field name is a field of the frozen class, and only raising
an error in that case.
A related issue is that dataclasses derived from frozen dataclasses are
automatically "promoted" to being frozen.
>>> @dataclass(frozen=True)
... class A:
... i: int
...
>>> @dataclass
... class B(A):
... j: int
...
>>> b = B(1, 2)
>>> b.j = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\home\eric\local\python\cpython\lib\dataclasses.py", line
452, in _frozen_setattr
raise FrozenInstanceError(f'cannot assign to field {name!r}')
dataclasses.FrozenInstanceError: cannot assign to field 'j'
Maybe it should be an error to declare B as non-frozen?
Eric.
More information about the Python-Dev
mailing list