You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: peps/pep-9999.rst
+18-18Lines changed: 18 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,8 +6,8 @@ Discussions-To: <REQUIRED: URL of current canonical discussion thread>
6
6
Status: Draft
7
7
Type: Standards Track
8
8
Topic: Typing
9
-
Created: ?-Nov-2024
10
-
Python-Version: 3.?
9
+
Created: 18-Nov-2024
10
+
Python-Version: 3.14
11
11
12
12
13
13
Abstract
@@ -20,14 +20,14 @@ This PEP proposes expanding the scope of ``ReadOnly`` to class and protocol
20
20
attributes, as a single concise way to mark them read-only. Some parity changes
21
21
are also made to :data:`typing.Final`.
22
22
23
-
Akin to :pep:`705`, it makes no Python grammar changes. Correct usage of
23
+
Akin to :pep:`705`, it makes no changes to setting attributes at runtime. Correct usage of
24
24
read-only attributes is intended to be enforced only by static type checkers.
25
25
26
26
27
27
Motivation
28
28
==========
29
29
30
-
Python type system lacks a single concise way to mark an :term:`attribute` read-only.
30
+
The Python type system lacks a single concise way to mark an :term:`attribute` read-only.
31
31
This feature is common in other object-oriented languages (such as `C# <https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly>`_),
32
32
and is useful for restricting attribute mutation at a type checker level, as well
33
33
as defining a broad interface for structural subtyping.
@@ -37,7 +37,7 @@ as defining a broad interface for structural subtyping.
37
37
Classes
38
38
-------
39
39
40
-
There are 3 major ways of achieving read-only attributes, honored by type checkers:
40
+
Today, there are three major ways of achieving read-only attributes, honored by type checkers:
41
41
42
42
* annotating the attribute with :data:`typing.Final`::
43
43
@@ -54,7 +54,7 @@ There are 3 major ways of achieving read-only attributes, honored by type checke
54
54
55
55
- Supported by :mod:`dataclasses` (and type checkers since `typing#1669 <https://github.com/python/typing/pull/1669>`_).
56
56
- Overriding ``number`` is not possible - the specification of ``Final``
57
-
imposes the name cannot be overridden in subclasses.
57
+
imposes that the name cannot be overridden in subclasses.
58
58
59
59
* read-only proxy via ``@property``::
60
60
@@ -97,10 +97,10 @@ Protocols
97
97
---------
98
98
99
99
Paraphrasing `this post <https://github.com/python/typing/discussions/1525>`_,
100
-
there is no way of defining a :class:`~typing.Protocol`, such that the only
100
+
there is no way of defining an attribute ``name: T`` on a :class:`~typing.Protocol`, such that the only
The above are satisfiable at runtime by all of the following:
@@ -135,9 +135,9 @@ Rationale
135
135
136
136
These problems can be resolved by an attribute-level :external+typing:term:`type qualifier`.
137
137
``ReadOnly`` has been chosen for this role, as its name conveys the intent well,
138
-
and the newly proposed changes complement its semantics defined in the :pep:`705`.
138
+
and the newly proposed changes complement its semantics defined in :pep:`705`.
139
139
140
-
A class with a read-only instance attribute can be now defined as such::
140
+
A class with a read-only instance attribute can now be defined as::
141
141
142
142
from typing import ReadOnly
143
143
@@ -146,7 +146,7 @@ A class with a read-only instance attribute can be now defined as such::
146
146
def __init__(self, id: int) -> None:
147
147
self.id: ReadOnly = id
148
148
149
-
...and a protocol described in :ref:`protocols` is now just::
149
+
...and the protocol described in :ref:`protocols` is now just::
150
150
151
151
from typing import Protocol, ReadOnly
152
152
@@ -170,10 +170,10 @@ Specification
170
170
171
171
The :external+py3.13:data:`typing.ReadOnly` :external+typing:term:`type qualifier`
172
172
becomes a valid annotation for :term:`attributes <attribute>` of classes and protocols.
173
-
It is used to indicate that an attribute should not be reassigned or ``del``\ eted.
173
+
Type checkers should error on any attempt to reassign or ``del``\ ete an attribute annotated with ``ReadOnly``.
174
174
175
-
The deletability rule should be extended to ``Final`` as well, as it is currently
176
-
not specified.
175
+
Type checkers should also error on any attempt to delete an attribute annotated as ``Final``.
176
+
(This is not currently specified.)
177
177
178
178
Akin to ``Final``, read-only attributes do not influence the mutability of
179
179
the assigned object. Immutable ABCs and containers may be used in combination with
@@ -198,8 +198,8 @@ The explicit type in ``ReadOnly[<type>]`` can be omitted if the declaration has
198
198
an initializing value. A type checker should apply its usual type inference
199
199
rules to determine the type of ``name``.
200
200
201
-
If an attribute is already implied to be read-only, like in the frozen :ref:`classes`,
202
-
explicit declarations should be permitted and seen as equivalent, except ``Final``
201
+
If an attribute is already implied to be read-only, like in frozen :ref:`classes`,
202
+
explicit declarations should be permitted and seen as equivalent, except that ``Final``
203
203
additionally forbids overriding in subclasses:
204
204
205
205
.. code-block:: python
@@ -364,7 +364,7 @@ Borrowing from :pep:`PEP 705 <705#inheritance>`:
364
364
print(self.foo, self.bar, self.baz)
365
365
366
366
* In a protocol attribute declaration, ``name: ReadOnly[T]`` indicates that a structural
367
-
subtype must support ``.name`` access, and the returned value is compatible with ``T``::
367
+
subtype must support ``.name`` access, and the returned value is assignable to ``T``::
368
368
369
369
class HasName(Protocol):
370
370
name: ReadOnly[str]
@@ -496,7 +496,7 @@ Extending initialization
496
496
Mechanisms such as :func:`dataclasses.__post_init__` or attrs' `initialization hooks <https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization>`_
497
497
augment initialization by providing a set of dunder hooks which will be called
498
498
once during instance creation. The current rules would disallow assignment in those
499
-
hooks. Specifying any single method in the pep isn't enough, as the naming and
499
+
hooks. Specifying any single method in the PEP isn't enough, as the naming and
500
500
functionality differs between mechanisms (``__post_init__`` vs ``__attrs_post_init__``).
501
501
502
502
``ReadOnly[ClassVar[...]]`` and ``__init_subclass__``
0 commit comments