Treatment of `Final` attributes in dataclass-likes

Thanks for clarifying the intention, especially with regards to this example:

class Item:
    def __init__(self, x: int = 3) -> None:
        self.x: Final[int] = x

This being said, I also think the re-use of Final as proposed here is too overloaded. The motivation to special-case Final in dataclasses isn’t too compelling on the basis of what it’s trying to prevent (instance.var = obj doesn’t work with type-checkers regardless of whether var: Final means var: ClassVar or the read-only instance variable proposal here).

IMO, implementing one of these (then deprecating and eventually removing the ability of Final to create dataclass fields) is a better solution:

Preventing Final from meaning both (1) read-only instance variables and (2) non-overridable dataclasses fields in subclasses would allow the future ability to specify field defaults in subclasses without affecting read-only status.

Concept draft
import typing_extensions as _t
import dataclasses as _dc

@_dc.dataclass
class Data:
    a: _t.ReadOnly[int]  # Read-only dataclass field with no default
    b: _t.ReadOnly[int] = 0  # Read-only field with default
    c: int = 0  # Normal field
    d: _t.Final[int] = 0  # Non-overridable class variable
    e: _t.Final[_dc.Field[int]] = 0  # Non-overridable field, instance variable is **not** read-only
    f: _t.Final[_t.ReadOnly[_dc.Field[int]]] = 0  # Non-overridable field which is read-only in instances

@_dc.dataclass
class Sub(Data):
    b: _t.ReadOnly[int] = 1  # Default changed, instance variables are still read-only
    c: _t.ReadOnly[int] = 1  # Mutable override error
1 Like