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.

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to