Skip to content

Commit f57cdbe

Browse files
authored
PEP 767: Include __init_subclass__ in initialization (#4181)
1 parent a9cb879 commit f57cdbe

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

peps/pep-0767.rst

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ Today, there are three major ways of achieving read-only attributes, honored by
9898
Protocols
9999
---------
100100

101-
A read-only attribute ``name: T`` on a :class:`~typing.Protocol` in principle
102-
defines two requirements:
101+
Suppose a :class:`~typing.Protocol` member ``name: T`` defining two requirements:
103102

104103
1. ``hasattr(obj, "name")``
105104
2. ``isinstance(obj.name, T)``
@@ -251,7 +250,12 @@ Initialization
251250

252251
Assignment to a read-only attribute can only occur in the class declaring the attribute.
253252
There is no restriction to how many times the attribute can be assigned to.
254-
The assignment must be allowed in the following contexts:
253+
Depending on the kind of the attribute, they can be assigned to at different sites:
254+
255+
Instance Attributes
256+
'''''''''''''''''''
257+
258+
Assignment to an instance attribute must be allowed in the following contexts:
255259

256260
* In ``__init__``, on the instance received as the first parameter (likely, ``self``).
257261
* In ``__new__``, on instances of the declaring class created via a call
@@ -267,9 +271,6 @@ Additionally, a type checker may choose to allow the assignment:
267271
* In ``@classmethod``\ s, on instances of the declaring class created via
268272
a call to the class' or super-class' ``__new__`` method.
269273

270-
Note that a child class cannot assign to any read-only attributes of a parent class
271-
in any of the aforementioned contexts, unless the attribute is redeclared.
272-
273274
.. code-block:: python
274275
275276
from collections import abc
@@ -332,6 +333,25 @@ in any of the aforementioned contexts, unless the attribute is redeclared.
332333
self.numerator, self.denominator = f.as_integer_ratio()
333334
return self
334335
336+
Class Attributes
337+
''''''''''''''''
338+
339+
Read-only class attributes are attributes annotated as both ``ReadOnly`` and ``ClassVar``.
340+
Assignment to such attributes must be allowed in the following contexts:
341+
342+
* At declaration in the body of the class.
343+
* In ``__init_subclass__``, on the class object received as the first parameter (likely, ``cls``).
344+
345+
.. code-block:: python
346+
347+
class URI:
348+
protocol: ReadOnly[ClassVar[str]] = ""
349+
350+
def __init_subclass__(cls, protocol: str = "") -> None:
351+
cls.protocol = protocol
352+
353+
class File(URI, protocol="file"): ...
354+
335355
When a class-level declaration has an initializing value, it can serve as a `flyweight <https://en.wikipedia.org/wiki/Flyweight_pattern>`_
336356
default for instances:
337357

@@ -367,8 +387,8 @@ protocols or ABCs)::
367387
Subtyping
368388
---------
369389

370-
Read-only attributes are covariant. This has a few subtyping implications.
371-
Borrowing from :pep:`705#inheritance`:
390+
The inability to reassign read-only attributes makes them covariant.
391+
This has a few subtyping implications. Borrowing from :pep:`705#inheritance`:
372392

373393
* Read-only attributes can be redeclared as writable attributes, descriptors
374394
or class variables::
@@ -493,9 +513,6 @@ Interaction with Other Type Qualifiers
493513
This is consistent with the interaction of ``ReadOnly`` and :class:`typing.TypedDict`
494514
defined in :pep:`705`.
495515

496-
An attribute annotated as both ``ReadOnly`` and ``ClassVar`` can only be assigned to
497-
at declaration in the class body.
498-
499516
An attribute cannot be annotated as both ``ReadOnly`` and ``Final``, as the two
500517
qualifiers differ in semantics, and ``Final`` is generally more restrictive.
501518
``Final`` remains allowed as an annotation of attributes that are only implied
@@ -604,23 +621,6 @@ to allow initialization in. This however could easily result in users mistakenly
604621
or purposefully breaking the aforementioned invariants. It is also a fairly
605622
big ask for a relatively niche feature.
606623

607-
``ReadOnly[ClassVar[...]]`` and ``__init_subclass__``
608-
-----------------------------------------------------
609-
610-
Should read-only class variables be assignable to within the declaring class'
611-
``__init_subclass__``?
612-
613-
.. code-block:: python
614-
615-
class URI:
616-
protocol: ReadOnly[ClassVar[str]] = ""
617-
618-
def __init_subclass__(cls, protocol: str = "") -> None:
619-
cls.foo = protocol
620-
621-
class File(URI, protocol="file"): ...
622-
623-
624624
Footnotes
625625
=========
626626

0 commit comments

Comments
 (0)