On 22 February 2018 at 10:55, Eric V. Smith <eric@trueblade.com> wrote:
On 2/22/2018 1:56 AM, Raymond Hettinger wrote:
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.

How about checking that the type of self is the type where decorator was applied? For example (pseudocode):

def dataclass(cls, ...):
    def _set_attr(self, attr, value):
        if type(self) is not cls:
             use super()
        else:
            raise AttributeError
    cls.__setattr__ = _set_attr

It can be also more sophisticated, for example raising for all fields on class where frozen=True was used, while only on frozen fields for subclasses.

--
Ivan